@buenos_andres/contracts 0.1.4 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,607 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- // MyFun Contracts v0.1.4 (token/FungibleToken.compact)
3
-
4
- pragma language_version >= 0.16.0;
5
-
6
- /**
7
- * @module FungibleToken
8
- * @description An unshielded FungibleToken library.
9
- *
10
- * @notice One notable difference regarding this implementation and the EIP20 spec
11
- * consists of the token size. Uint<128> is used as the token size because Uint<256>
12
- * cannot be supported.
13
- * This is due to encoding limits on the midnight circuit backend:
14
- * https://github.com/midnightntwrk/compactc/issues/929
15
- *
16
- * @notice At the moment Midnight does not support contract-to-contract communication, but
17
- * there are ongoing efforts to enable this in the future. Thus, the main circuits of this module
18
- * restrict developers from sending tokens to contracts; however, we provide developers
19
- * the ability to experiment with sending tokens to contracts using the `_unsafe`
20
- * transfer methods. Once contract-to-contract communication is available we will follow the
21
- * deprecation plan outlined below:
22
- *
23
- * Initial Minor Version Change:
24
- *
25
- * - Mark _unsafeFN as deprecated and emit a warning if possible.
26
- * - Keep its implementation intact so existing callers continue to work.
27
- *
28
- * Later Major Version Change:
29
- *
30
- * - Drop _unsafeFN and remove `isContract` guard from `FN`.
31
- * - By this point, anyone using _unsafeFN should have migrated to the now C2C-capable `FN`.
32
- *
33
- * Due to the vast incompatibilities with the EIP20 spec, it is our
34
- * opinion that this implementation should not be called ERC20 at this time
35
- * as this would be both very confusing and misleading. This may change as more
36
- * features become available. The list of missing features is as follows:
37
- *
38
- * - Full uint256 support.
39
- * - Events.
40
- * - Contract-to-contract calls.
41
- */
42
- module FungibleToken {
43
- import CompactStandardLibrary;
44
- import "../security/Initializable" prefix Initializable_;
45
- import "../utils/Utils" prefix Utils_;
46
-
47
- /**
48
- * @description Mapping from account addresses to their token balances.
49
- * @type {Either<ZswapCoinPublicKey, ContractAddress>} account - The account address.
50
- * @type {Uint<128>} balance - The balance of the account.
51
- * @type {Map<account, balance>}
52
- * @type {Map<Either<ZswapCoinPublicKey, ContractAddress>, Uint<128>>} _balances
53
- */
54
- export ledger _balances: Map<Either<ZswapCoinPublicKey, ContractAddress>, Uint<128>>;
55
- /**
56
- * @description Mapping from owner accounts to spender accounts and their allowances.
57
- * @type {Either<ZswapCoinPublicKey, ContractAddress>} account - The owner account address.
58
- * @type {Either<ZswapCoinPublicKey, ContractAddress>} spender - The spender account address.
59
- * @type {Uint<128>} allowance - The amount allowed to be spent by the spender.
60
- * @type {Map<account, Map<spender, allowance>>}
61
- * @type {Map<Either<ZswapCoinPublicKey, ContractAddress>, Map<Either<ZswapCoinPublicKey, ContractAddress>, Uint<128>>>} _allowances
62
- */
63
- export ledger _allowances: Map<Either<ZswapCoinPublicKey, ContractAddress>, Map<Either<ZswapCoinPublicKey, ContractAddress>, Uint<128>>>;
64
-
65
- export ledger _totalSupply: Uint<128>;
66
-
67
- export sealed ledger _name: Opaque<"string">;
68
- export sealed ledger _symbol: Opaque<"string">;
69
- export sealed ledger _decimals: Uint<8>;
70
-
71
- /**
72
- * @description Initializes the contract by setting the name, symbol, and decimals.
73
- * @dev This MUST be called in the implementing contract's constructor. Failure to do so
74
- * can lead to an irreparable contract.
75
- *
76
- * @circuitInfo k=10, rows=71
77
- *
78
- * @param {Opaque<"string">} name_ - The name of the token.
79
- * @param {Opaque<"string">} symbol_ - The symbol of the token.
80
- * @param {Uint<8>} decimals_ - The number of decimals used to get the user representation.
81
- * @return {[]} - Empty tuple.
82
- */
83
- export circuit initialize(
84
- name_: Opaque<"string">,
85
- symbol_: Opaque<"string">,
86
- decimals_:Uint<8>
87
- ): [] {
88
- Initializable_initialize();
89
- _name = disclose(name_);
90
- _symbol = disclose(symbol_);
91
- _decimals = disclose(decimals_);
92
- }
93
-
94
- /**
95
- * @description Returns the token name.
96
- *
97
- * @circuitInfo k=10, rows=37
98
- *
99
- * Requirements:
100
- *
101
- * - Contract is initialized.
102
- *
103
- * @return {Opaque<"string">} - The token name.
104
- */
105
- export circuit name(): Opaque<"string"> {
106
- Initializable_assertInitialized();
107
- return _name;
108
- }
109
-
110
- /**
111
- * @description Returns the symbol of the token.
112
- *
113
- * @circuitInfo k=10, rows=37
114
- *
115
- * Requirements:
116
- *
117
- * - Contract is initialized.
118
- *
119
- * @return {Opaque<"string">} - The token name.
120
- */
121
- export circuit symbol(): Opaque<"string"> {
122
- Initializable_assertInitialized();
123
- return _symbol;
124
- }
125
-
126
- /**
127
- * @description Returns the number of decimals used to get its user representation.
128
- *
129
- * @circuitInfo k=10, rows=36
130
- *
131
- * Requirements:
132
- *
133
- * - Contract is initialized.
134
- *
135
- * @return {Uint<8>} - The account's token balance.
136
- */
137
- export circuit decimals(): Uint<8> {
138
- Initializable_assertInitialized();
139
- return _decimals;
140
- }
141
-
142
- /**
143
- * @description Returns the value of tokens in existence.
144
- *
145
- * @circuitInfo k=10, rows=36
146
- *
147
- * Requirements:
148
- *
149
- * - Contract is initialized.
150
- *
151
- * @return {Uint<128>} - The total supply of tokens.
152
- */
153
- export circuit totalSupply(): Uint<128> {
154
- Initializable_assertInitialized();
155
- return _totalSupply;
156
- }
157
-
158
- /**
159
- * @description Returns the value of tokens owned by `account`.
160
- *
161
- * @circuitInfo k=10, rows=310
162
- *
163
- * @dev Manually checks if `account` is a key in the map and returns 0 if it is not.
164
- *
165
- * Requirements:
166
- *
167
- * - Contract is initialized.
168
- *
169
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} account - The public key or contract address to query.
170
- * @return {Uint<128>} - The account's token balance.
171
- */
172
- export circuit balanceOf(account: Either<ZswapCoinPublicKey, ContractAddress>): Uint<128> {
173
- Initializable_assertInitialized();
174
- if (!_balances.member(disclose(account))) {
175
- return 0;
176
- }
177
-
178
- return _balances.lookup(disclose(account));
179
- }
180
-
181
- /**
182
- * @description Moves a `value` amount of tokens from the caller's account to `to`.
183
- *
184
- * @circuitInfo k=11, rows=1173
185
- *
186
- * @notice Transfers to contract addresses are currently disallowed until contract-to-contract
187
- * interactions are supported in Compact. This restriction prevents assets from
188
- * being inadvertently locked in contracts that cannot currently handle token receipt.
189
- *
190
- * Requirements:
191
- *
192
- * - Contract is initialized.
193
- * - `to` is not a ContractAddress.
194
- * - `to` is not the zero address.
195
- * - The caller has a balance of at least `value`.
196
- *
197
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} to - The recipient of the transfer, either a user or a contract.
198
- * @param {Uint<128>} value - The amount to transfer.
199
- * @return {Boolean} - As per the IERC20 spec, this MUST return true.
200
- */
201
- export circuit transfer(to: Either<ZswapCoinPublicKey, ContractAddress>, value: Uint<128>): Boolean {
202
- Initializable_assertInitialized();
203
- assert(!Utils_isContractAddress(to), "FungibleToken: Unsafe Transfer");
204
- return _unsafeTransfer(to, value);
205
- }
206
-
207
- /**
208
- * @description Unsafe variant of `transfer` which allows transfers to contract addresses.
209
- *
210
- * @circuitInfo k=11, rows=1170
211
- *
212
- * @warning Transfers to contract addresses are considered unsafe because contract-to-contract
213
- * calls are not currently supported. Tokens sent to a contract address may become irretrievable.
214
- * Once contract-to-contract calls are supported, this circuit may be deprecated.
215
- *
216
- * Requirements:
217
- *
218
- * - Contract is initialized.
219
- * - `to` is not the zero address.
220
- * - The caller has a balance of at least `value`.
221
- *
222
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} to - The recipient of the transfer, either a user or a contract.
223
- * @param {Uint<128>} value - The amount to transfer.
224
- * @return {Boolean} - As per the IERC20 spec, this MUST return true.
225
- */
226
- export circuit _unsafeTransfer(to: Either<ZswapCoinPublicKey, ContractAddress>, value: Uint<128>): Boolean {
227
- Initializable_assertInitialized();
228
- const owner = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
229
- _unsafeUncheckedTransfer(owner, to, value);
230
- return true;
231
- }
232
-
233
- /**
234
- * @description Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner`
235
- * through `transferFrom`. This value changes when `approve` or `transferFrom` are called.
236
- *
237
- * @circuitInfo k=10, rows=624
238
- *
239
- * @dev Manually checks if `owner` and `spender` are keys in the map and returns 0 if they are not.
240
- *
241
- * Requirements:
242
- *
243
- * - Contract is initialized.
244
- *
245
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} owner - The public key or contract address of approver.
246
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} spender - The public key or contract address of spender.
247
- * @return {Uint<128>} - The `spender`'s allowance over `owner`'s tokens.
248
- */
249
- export circuit allowance(
250
- owner: Either<ZswapCoinPublicKey, ContractAddress>,
251
- spender: Either<ZswapCoinPublicKey, ContractAddress>
252
- ): Uint<128> {
253
- Initializable_assertInitialized();
254
- if (!_allowances.member(disclose(owner)) || !_allowances.lookup(owner).member(disclose(spender))) {
255
- return 0;
256
- }
257
-
258
- return _allowances.lookup(owner).lookup(disclose(spender));
259
- }
260
-
261
- /**
262
- * @description Sets a `value` amount of tokens as allowance of `spender` over the caller's tokens.
263
- *
264
- * @circuitInfo k=10, rows=452
265
- *
266
- * Requirements:
267
- *
268
- * - Contract is initialized.
269
- * - `spender` is not the zero address.
270
- *
271
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} spender - The Zswap key or ContractAddress that may spend on behalf of the caller.
272
- * @param {Uint<128>} value - The amount of tokens the `spender` may spend.
273
- * @return {Boolean} - Returns a boolean value indicating whether the operation succeeded.
274
- */
275
- export circuit approve(spender: Either<ZswapCoinPublicKey, ContractAddress>, value: Uint<128>): Boolean {
276
- Initializable_assertInitialized();
277
-
278
- const owner = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
279
- _approve(owner, spender, value);
280
- return true;
281
- }
282
-
283
- /**
284
- * @description Moves `value` tokens from `from` to `to` using the allowance mechanism.
285
- * `value` is the deducted from the caller's allowance.
286
- *
287
- * @circuitInfo k=11, rows=1821
288
- *
289
- * @notice Transfers to contract addresses are currently disallowed until contract-to-contract
290
- * interactions are supported in Compact. This restriction prevents assets from
291
- * being inadvertently locked in contracts that cannot currently handle token receipt.
292
- *
293
- * Requirements:
294
- *
295
- * - Contract is initialized.
296
- * - `from` is not the zero address.
297
- * - `from` must have a balance of at least `value`.
298
- * - `to` is not the zero address.
299
- * - `to` is not a ContractAddress.
300
- * - The caller has an allowance of `from`'s tokens of at least `value`.
301
- *
302
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} from - The current owner of the tokens for the transfer, either a user or a contract.
303
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} to - The recipient of the transfer, either a user or a contract.
304
- * @param {Uint<128>} value - The amount to transfer.
305
- * @return {Boolean} - As per the IERC20 spec, this MUST return true.
306
- */
307
- export circuit transferFrom(
308
- from: Either<ZswapCoinPublicKey, ContractAddress>,
309
- to: Either<ZswapCoinPublicKey, ContractAddress>,
310
- value: Uint<128>
311
- ): Boolean {
312
- Initializable_assertInitialized();
313
- assert(!Utils_isContractAddress(to), "FungibleToken: Unsafe Transfer");
314
- return _unsafeTransferFrom(from, to, value);
315
- }
316
-
317
- /**
318
- * @description Unsafe variant of `transferFrom` which allows transfers to contract addresses.
319
- *
320
- * @circuitInfo k=11, rows=1818
321
- *
322
- * @warning Transfers to contract addresses are considered unsafe because contract-to-contract
323
- * calls are not currently supported. Tokens sent to a contract address may become irretrievable.
324
- * Once contract-to-contract calls are supported, this circuit may be deprecated.
325
- *
326
- * Requirements:
327
- *
328
- * - Contract is initialized.
329
- * - `from` is not the zero address.
330
- * - `from` must have a balance of at least `value`.
331
- * - `to` is not the zero address.
332
- * - The caller has an allowance of `from`'s tokens of at least `value`.
333
- *
334
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} from - The current owner of the tokens for the transfer, either a user or a contract.
335
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} to - The recipient of the transfer, either a user or a contract.
336
- * @param {Uint<128>} value - The amount to transfer.
337
- * @return {Boolean} - As per the IERC20 spec, this MUST return true.
338
- */
339
- export circuit _unsafeTransferFrom(
340
- from: Either<ZswapCoinPublicKey, ContractAddress>,
341
- to: Either<ZswapCoinPublicKey, ContractAddress>,
342
- value: Uint<128>
343
- ): Boolean {
344
- Initializable_assertInitialized();
345
-
346
- const spender = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
347
- _spendAllowance(from, spender, value);
348
- _unsafeUncheckedTransfer(from, to, value);
349
- return true;
350
- }
351
-
352
- /**
353
- * @description Moves a `value` amount of tokens from `from` to `to`.
354
- * This circuit is equivalent to {transfer}, and can be used to
355
- * e.g. implement automatic token fees, slashing mechanisms, etc.
356
- *
357
- * @circuitInfo k=11, rows=1312
358
- *
359
- * @notice Transfers to contract addresses are currently disallowed until contract-to-contract
360
- * interactions are supported in Compact. This restriction prevents assets from
361
- * being inadvertently locked in contracts that cannot currently handle token receipt.
362
- *
363
- * Requirements:
364
- *
365
- * - Contract is initialized.
366
- * - `from` is not be the zero address.
367
- * - `from` must have at least a balance of `value`.
368
- * - `to` must not be the zero address.
369
- * - `to` must not be a ContractAddress.
370
- *
371
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} from - The owner of the tokens to transfer.
372
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} to - The receipient of the transferred tokens.
373
- * @param {Uint<128>} value - The amount of tokens to transfer.
374
- * @return {[]} - Empty tuple.
375
- */
376
- export circuit _transfer(
377
- from: Either<ZswapCoinPublicKey, ContractAddress>,
378
- to: Either<ZswapCoinPublicKey, ContractAddress>,
379
- value: Uint<128>
380
- ): [] {
381
- Initializable_assertInitialized();
382
- assert(!Utils_isContractAddress(to), "FungibleToken: Unsafe Transfer");
383
- _unsafeUncheckedTransfer(from, to, value);
384
- }
385
-
386
- /**
387
- * @description Unsafe variant of `transferFrom` which allows transfers to contract addresses.
388
- *
389
- * @circuitInfo k=11, rows=1309
390
- *
391
- * @warning Transfers to contract addresses are considered unsafe because contract-to-contract
392
- * calls are not currently supported. Tokens sent to a contract address may become irretrievable.
393
- * Once contract-to-contract calls are supported, this circuit may be deprecated.
394
- *
395
- * Requirements:
396
- *
397
- * - Contract is initialized.
398
- * - `from` is not the zero address.
399
- * - `to` is not the zero address.
400
- *
401
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} from - The owner of the tokens to transfer.
402
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} to - The receipient of the transferred tokens.
403
- * @param {Uint<128>} value - The amount of tokens to transfer.
404
- * @return {[]} - Empty tuple.
405
- */
406
- export circuit _unsafeUncheckedTransfer(
407
- from: Either<ZswapCoinPublicKey, ContractAddress>,
408
- to: Either<ZswapCoinPublicKey, ContractAddress>,
409
- value: Uint<128>
410
- ): [] {
411
- Initializable_assertInitialized();
412
- assert(!Utils_isKeyOrAddressZero(from), "FungibleToken: invalid sender");
413
- assert(!Utils_isKeyOrAddressZero(to), "FungibleToken: invalid receiver");
414
-
415
- _update(from, to, value);
416
- }
417
-
418
- /**
419
- * @description Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
420
- * (or `to`) is the zero address.
421
- * @dev Checks for a mint overflow in order to output a more readable error message.
422
- *
423
- * @circuitInfo k=11, rows=1305
424
- *
425
- * Requirements:
426
- *
427
- * - Contract is initialized.
428
- *
429
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} from - The original owner of the tokens moved (which is 0 if tokens are minted).
430
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} to - The recipient of the tokens moved (which is 0 if tokens are burned).
431
- * @param {Uint<128>} value - The amount of tokens moved from `from` to `to`.
432
- * @return {[]} - Empty tuple.
433
- */
434
- circuit _update(
435
- from: Either<ZswapCoinPublicKey, ContractAddress>,
436
- to: Either<ZswapCoinPublicKey, ContractAddress>,
437
- value: Uint<128>
438
- ): [] {
439
- Initializable_assertInitialized();
440
- if (Utils_isKeyOrAddressZero(disclose(from))) {
441
- // Mint
442
- const MAX_UINT128 = 340282366920938463463374607431768211455;
443
- assert(MAX_UINT128 - _totalSupply >= value, "FungibleToken: arithmetic overflow");
444
-
445
- _totalSupply = disclose(_totalSupply + value as Uint<128>);
446
- } else {
447
- const fromBal = balanceOf(from);
448
- assert(fromBal >= value, "FungibleToken: insufficient balance");
449
- _balances.insert(disclose(from), disclose(fromBal - value as Uint<128>));
450
- }
451
-
452
- if (Utils_isKeyOrAddressZero(disclose(to))) {
453
- // Burn
454
- _totalSupply = disclose(_totalSupply - value as Uint<128>);
455
- } else {
456
- const toBal = balanceOf(to);
457
- _balances.insert(disclose(to), disclose(toBal + value as Uint<128>));
458
- }
459
- }
460
-
461
- /**
462
- * @description Creates a `value` amount of tokens and assigns them to `account`,
463
- * by transferring it from the zero address. Relies on the `update` mechanism.
464
- *
465
- * @circuitInfo k=10, rows=752
466
- *
467
- * @notice Transfers to contract addresses are currently disallowed until contract-to-contract
468
- * interactions are supported in Compact. This restriction prevents assets from
469
- * being inadvertently locked in contracts that cannot currently handle token receipt.
470
- *
471
- * Requirements:
472
- *
473
- * - Contract is initialized.
474
- * - `to` is not a ContractAddress.
475
- * - `account` is not the zero address.
476
- *
477
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} account - The recipient of tokens minted.
478
- * @param {Uint<128>} value - The amount of tokens minted.
479
- * @return {[]} - Empty tuple.
480
- */
481
- export circuit _mint(
482
- account: Either<ZswapCoinPublicKey, ContractAddress>,
483
- value: Uint<128>
484
- ): [] {
485
- Initializable_assertInitialized();
486
- assert(!Utils_isContractAddress(account), "FungibleToken: Unsafe Transfer");
487
- _unsafeMint(account, value);
488
- }
489
-
490
- /**
491
- * @description Unsafe variant of `_mint` which allows transfers to contract addresses.
492
- *
493
- * @circuitInfo k=10, rows=749
494
- *
495
- * @warning Transfers to contract addresses are considered unsafe because contract-to-contract
496
- * calls are not currently supported. Tokens sent to a contract address may become irretrievable.
497
- * Once contract-to-contract calls are supported, this circuit may be deprecated.
498
- *
499
- * Requirements:
500
- *
501
- * - Contract is initialized.
502
- * - `account` is not the zero address.
503
- *
504
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} account - The recipient of tokens minted.
505
- * @param {Uint<128>} value - The amount of tokens minted.
506
- * @return {[]} - Empty tuple.
507
- */
508
- export circuit _unsafeMint(
509
- account: Either<ZswapCoinPublicKey, ContractAddress>,
510
- value: Uint<128>
511
- ): [] {
512
- Initializable_assertInitialized();
513
- assert(!Utils_isKeyOrAddressZero(account), "FungibleToken: invalid receiver");
514
- _update(burnAddress(), account, value);
515
- }
516
-
517
- /**
518
- * @description Destroys a `value` amount of tokens from `account`, lowering the total supply.
519
- * Relies on the `_update` mechanism.
520
- *
521
- * @circuitInfo k=10, rows=773
522
- *
523
- * Requirements:
524
- *
525
- * - Contract is initialized.
526
- * - `account` is not the zero address.
527
- * - `account` must have at least a balance of `value`.
528
- *
529
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} account - The target owner of tokens to burn.
530
- * @param {Uint<128>} value - The amount of tokens to burn.
531
- * @return {[]} - Empty tuple.
532
- */
533
- export circuit _burn(
534
- account: Either<ZswapCoinPublicKey, ContractAddress>,
535
- value: Uint<128>
536
- ): [] {
537
- Initializable_assertInitialized();
538
- assert(!Utils_isKeyOrAddressZero(account), "FungibleToken: invalid sender");
539
- _update(account, burnAddress(), value);
540
- }
541
-
542
- /**
543
- * @description Sets `value` as the allowance of `spender` over the `owner`'s tokens.
544
- * This circuit is equivalent to `approve`, and can be used to
545
- *
546
- * @circuitInfo k=10, rows=583
547
- *
548
- * e.g. set automatic allowances for certain subsystems, etc.
549
- *
550
- * Requirements:
551
- *
552
- * - Contract is initialized.
553
- * - `owner` is not the zero address.
554
- * - `spender` is not the zero address.
555
- *
556
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} owner - The owner of the tokens.
557
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} spender - The spender of the tokens.
558
- * @param {Uint<128>} value - The amount of tokens `spender` may spend on behalf of `owner`.
559
- * @return {[]} - Empty tuple.
560
- */
561
- export circuit _approve(
562
- owner: Either<ZswapCoinPublicKey, ContractAddress>,
563
- spender: Either<ZswapCoinPublicKey, ContractAddress>,
564
- value: Uint<128>
565
- ): [] {
566
- Initializable_assertInitialized();
567
- assert(!Utils_isKeyOrAddressZero(owner), "FungibleToken: invalid owner");
568
- assert(!Utils_isKeyOrAddressZero(spender), "FungibleToken: invalid spender");
569
- if (!_allowances.member(disclose(owner))) {
570
- // If owner doesn't exist, create and insert a new sub-map directly
571
- _allowances.insert(disclose(owner), default<Map<Either<ZswapCoinPublicKey, ContractAddress>, Uint<128>>>);
572
- }
573
- _allowances.lookup(owner).insert(disclose(spender), disclose(value));
574
- }
575
-
576
- /**
577
- * @description Updates `owner`'s allowance for `spender` based on spent `value`.
578
- * Does not update the allowance value in case of infinite allowance.
579
- *
580
- * @circuitInfo k=10, rows=931
581
- *
582
- * Requirements:
583
- *
584
- * - Contract is initialized.
585
- * - `spender` must have at least an allowance of `value` from `owner`.
586
- *
587
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} owner - The owner of the tokens.
588
- * @param {Either<ZswapCoinPublicKey, ContractAddress>} spender - The spender of the tokens.
589
- * @param {Uint<128>} value - The amount of token allowance to spend.
590
- * @return {[]} - Empty tuple.
591
- */
592
- export circuit _spendAllowance(
593
- owner: Either<ZswapCoinPublicKey, ContractAddress>,
594
- spender: Either<ZswapCoinPublicKey, ContractAddress>,
595
- value: Uint<128>
596
- ): [] {
597
- Initializable_assertInitialized();
598
- assert((_allowances.member(disclose(owner)) && _allowances.lookup(owner).member(disclose(spender))), "FungibleToken: insufficient allowance");
599
-
600
- const currentAllowance = _allowances.lookup(owner).lookup(disclose(spender));
601
- const MAX_UINT128 = 340282366920938463463374607431768211455;
602
- if (currentAllowance < MAX_UINT128) {
603
- assert(currentAllowance >= value, "FungibleToken: insufficient allowance");
604
- _approve(owner, spender, currentAllowance - value as Uint<128>);
605
- }
606
- }
607
- }