@openzeppelin/compact-contracts 0.4.0-alpha.2 → 0.4.0-alpha.3
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.
- package/access/AccessControl.compact +1 -1
- package/access/Ownable.compact +1 -1
- package/access/ShieldedAccessControl.compact +1 -1
- package/access/ZOwnablePK.compact +1 -1
- package/crypto/EcdhMask.compact +1 -1
- package/crypto/Ecdsa.compact +1 -1
- package/crypto/Eip712.compact +1 -1
- package/crypto/ElGamal.compact +44 -3
- package/multisig/EcdsaSignerManager.compact +1 -1
- package/multisig/ForwarderPrivate.compact +1 -1
- package/multisig/ForwarderShielded.compact +1 -1
- package/multisig/ForwarderUnshielded.compact +1 -1
- package/multisig/ProposalManager.compact +1 -1
- package/multisig/ShieldedTreasury.compact +1 -1
- package/multisig/ShieldedTreasuryStateless.compact +1 -1
- package/multisig/Signer.compact +1 -1
- package/multisig/UnshieldedTreasury.compact +1 -1
- package/multisig/examples/ForwarderPrivateExample.compact +1 -1
- package/multisig/examples/ForwarderShieldedExample.compact +1 -1
- package/multisig/examples/ForwarderUnshieldedExample.compact +1 -1
- package/multisig/examples/NativeShieldedTokenIssuerExample.compact +1 -1
- package/multisig/examples/ShieldedMultiSigV2Example.compact +1 -1
- package/multisig/presets/NativeShieldedTokenIssuer.compact +18 -3
- package/multisig/presets/ShieldedMultiSigV2.compact +1 -1
- package/package.json +1 -1
- package/security/Allowlist.compact +1 -1
- package/security/Blocklist.compact +1 -1
- package/security/Initializable.compact +1 -1
- package/security/Pausable.compact +1 -1
- package/token/ConfidentialFungibleToken.compact +268 -69
- package/token/FungibleToken.compact +1 -1
- package/token/MultiToken.compact +1 -1
- package/token/NativeShieldedToken.compact +59 -10
- package/token/NativeShieldedTokenCore.compact +41 -9
- package/token/NativeShieldedTokenFamily.compact +60 -10
- package/token/NonFungibleToken.compact +56 -12
- package/token/extensions/ConfidentialFungibleTokenPublicSupply.compact +1 -1
- package/token/extensions/NativeShieldedTokenDerivedNonce.compact +1 -1
- package/token/extensions/NativeShieldedTokenFamilyPublicSupply.compact +2 -2
- package/token/extensions/NativeShieldedTokenPublicSupply.compact +2 -2
- package/utils/EvmAbi.compact +1 -1
- package/utils/Utils.compact +11 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (token/NativeShieldedToken.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -20,6 +20,10 @@ pragma language_version >= 0.26.0;
|
|
|
20
20
|
* share one set of core state (a single init flag and one name/symbol/decimals).
|
|
21
21
|
* Pick one flavor per contract.
|
|
22
22
|
*
|
|
23
|
+
* @notice Recipients must be coin public keys: contract-addressed recipients
|
|
24
|
+
* are not supported at this layer. For a coin the contract holds itself, use
|
|
25
|
+
* `_mintToSelf`, which mints to `kernel.self()` and claims it in the same call.
|
|
26
|
+
*
|
|
23
27
|
* @notice This module exposes composable building blocks for minting and
|
|
24
28
|
* burning native shielded coins. It does NOT include access control: consuming
|
|
25
29
|
* contracts compose that via the module/contract pattern (Ownable,
|
|
@@ -190,25 +194,65 @@ module NativeShieldedToken {
|
|
|
190
194
|
* recipient; callers SHOULD deliver it out of band. Wallets cannot detect
|
|
191
195
|
* contract-minted coins by scanning the chain.
|
|
192
196
|
*
|
|
193
|
-
* @constraints k=14, rows=
|
|
197
|
+
* @constraints k=14, rows=10450
|
|
194
198
|
*
|
|
195
199
|
* Requirements:
|
|
196
200
|
*
|
|
197
201
|
* - Contract is initialized.
|
|
198
202
|
* - `recipient` is not zero.
|
|
199
203
|
*
|
|
200
|
-
* @param {
|
|
204
|
+
* @param {ZswapCoinPublicKey} recipient - The coin recipient.
|
|
201
205
|
* @param {Uint<64>} amount - Quantity to mint. Capped at `Uint<64>` by the protocol.
|
|
202
206
|
* @param {Bytes<32>} nonce - Caller-supplied nonce. Must be unique for this
|
|
203
207
|
* contract's color.
|
|
204
208
|
* @return {ShieldedCoinInfo} - The newly created coin's info (nonce, color, value).
|
|
205
209
|
*/
|
|
206
210
|
export circuit _mint(
|
|
207
|
-
recipient:
|
|
211
|
+
recipient: ZswapCoinPublicKey,
|
|
212
|
+
amount: Uint<64>,
|
|
213
|
+
nonce: Bytes<32>
|
|
214
|
+
): ShieldedCoinInfo {
|
|
215
|
+
return Core__mint(
|
|
216
|
+
_domain,
|
|
217
|
+
left<ZswapCoinPublicKey, ContractAddress>(recipient),
|
|
218
|
+
amount,
|
|
219
|
+
nonce
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* @description Mints `amount` to this contract itself, claiming the coin in
|
|
225
|
+
* the same call. Forwards to `NativeShieldedTokenCore._mint` with
|
|
226
|
+
* `right(kernel.self())`.
|
|
227
|
+
*
|
|
228
|
+
* @dev Nonce uniqueness is the caller's responsibility, as in `_mint`. Spend
|
|
229
|
+
* the coin later with `_burnFromSelf`, once it carries an `mt_index`.
|
|
230
|
+
*
|
|
231
|
+
* @notice The consumer SHOULD persist the returned coin info in its own
|
|
232
|
+
* ledger state: it is the contract's holding and is not otherwise
|
|
233
|
+
* recoverable.
|
|
234
|
+
*
|
|
235
|
+
* @constraints k=14, rows=16033
|
|
236
|
+
*
|
|
237
|
+
* Requirements:
|
|
238
|
+
*
|
|
239
|
+
* - Contract is initialized.
|
|
240
|
+
*
|
|
241
|
+
* @param {Uint<64>} amount - Quantity to mint. Capped at `Uint<64>` by the protocol.
|
|
242
|
+
* @param {Bytes<32>} nonce - Caller-supplied nonce. Must be unique for this
|
|
243
|
+
* contract's color.
|
|
244
|
+
* @return {ShieldedCoinInfo} - The newly created coin's info (nonce, color, value).
|
|
245
|
+
*/
|
|
246
|
+
export circuit _mintToSelf(
|
|
208
247
|
amount: Uint<64>,
|
|
209
248
|
nonce: Bytes<32>
|
|
210
249
|
): ShieldedCoinInfo {
|
|
211
|
-
return Core__mint(
|
|
250
|
+
return Core__mint(
|
|
251
|
+
_domain,
|
|
252
|
+
right<ZswapCoinPublicKey, ContractAddress>(kernel.self()),
|
|
253
|
+
amount,
|
|
254
|
+
nonce
|
|
255
|
+
);
|
|
212
256
|
}
|
|
213
257
|
|
|
214
258
|
/**
|
|
@@ -229,7 +273,7 @@ module NativeShieldedToken {
|
|
|
229
273
|
* `refundTo`; callers SHOULD deliver it out of band. Wallets cannot detect
|
|
230
274
|
* contract-sent coins by scanning the chain.
|
|
231
275
|
*
|
|
232
|
-
* @constraints k=16, rows=
|
|
276
|
+
* @constraints k=16, rows=41327
|
|
233
277
|
*
|
|
234
278
|
* Requirements:
|
|
235
279
|
*
|
|
@@ -241,17 +285,22 @@ module NativeShieldedToken {
|
|
|
241
285
|
*
|
|
242
286
|
* @param {ShieldedCoinInfo} coin - The coin to burn from.
|
|
243
287
|
* @param {Uint<128>} amount - Value to destroy. Must be <= `coin.value`.
|
|
244
|
-
* @param {
|
|
245
|
-
*
|
|
288
|
+
* @param {ZswapCoinPublicKey} refundTo - Where to route the unspent
|
|
289
|
+
* portion (`coin.value - amount`).
|
|
246
290
|
* @return {Maybe<ShieldedCoinInfo>} - The refund coin created for `refundTo`,
|
|
247
291
|
* or `none` if the coin was burned in full.
|
|
248
292
|
*/
|
|
249
293
|
export circuit _burn(
|
|
250
294
|
coin: ShieldedCoinInfo,
|
|
251
295
|
amount: Uint<128>,
|
|
252
|
-
refundTo:
|
|
296
|
+
refundTo: ZswapCoinPublicKey
|
|
253
297
|
): Maybe<ShieldedCoinInfo> {
|
|
254
|
-
return Core__burn(
|
|
298
|
+
return Core__burn(
|
|
299
|
+
_domain,
|
|
300
|
+
coin,
|
|
301
|
+
amount,
|
|
302
|
+
left<ZswapCoinPublicKey, ContractAddress>(refundTo)
|
|
303
|
+
);
|
|
255
304
|
}
|
|
256
305
|
|
|
257
306
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (token/NativeShieldedTokenCore.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -44,6 +44,18 @@ pragma language_version >= 0.26.0;
|
|
|
44
44
|
* compose `NativeShieldedTokenDerivedNonce` and pass its `_deriveNonce()`
|
|
45
45
|
* output, at the cost of making those mints recipient-public.
|
|
46
46
|
*
|
|
47
|
+
* @notice A recipient may be any coin public key, or this contract's own
|
|
48
|
+
* address. Any other contract address is rejected.
|
|
49
|
+
*
|
|
50
|
+
* @dev Recipient arm
|
|
51
|
+
* The ledger accepts a contract-addressed commitment only if the recipient
|
|
52
|
+
* contract's own call claims it as a shielded receive in the same transaction,
|
|
53
|
+
* and no primitive claims a receive on another contract's behalf. So the
|
|
54
|
+
* address arm is accepted only for `kernel.self()`, where `_mint` / `_burn`
|
|
55
|
+
* claim the coin themselves in the same call. The flavors do not expose the
|
|
56
|
+
* arm at all: they take a `ZswapCoinPublicKey` and offer `_mintToSelf` for
|
|
57
|
+
* contract-held coins.
|
|
58
|
+
*
|
|
47
59
|
* @dev Burn variants
|
|
48
60
|
* `_burn` destroys value from a coin provided within the current transaction
|
|
49
61
|
* (e.g. the caller's wallet pays the contract): it receives the coin and spends
|
|
@@ -222,21 +234,26 @@ module NativeShieldedTokenCore {
|
|
|
222
234
|
*
|
|
223
235
|
* @dev The caller is fully responsible for nonce uniqueness. Reusing a
|
|
224
236
|
* nonce for the same (domain, value, recipient) produces a duplicate
|
|
225
|
-
* commitment, which the protocol rejects.
|
|
237
|
+
* commitment, which the protocol rejects. A `right(kernel.self())` recipient
|
|
238
|
+
* is claimed via `receiveShielded` in this same call, so the consumer SHOULD
|
|
239
|
+
* persist the returned coin info: it is the contract's holding and is not
|
|
240
|
+
* otherwise recoverable.
|
|
226
241
|
*
|
|
227
242
|
* @notice The returned coin info is the only copy available to the
|
|
228
243
|
* recipient; callers SHOULD deliver it out of band. Wallets cannot detect
|
|
229
244
|
* contract-minted coins by scanning the chain.
|
|
230
245
|
*
|
|
231
|
-
* @constraints k=
|
|
246
|
+
* @constraints k=15, rows=16980
|
|
232
247
|
*
|
|
233
248
|
* Requirements:
|
|
234
249
|
*
|
|
235
250
|
* - Contract is initialized.
|
|
236
251
|
* - `recipient` is not zero.
|
|
252
|
+
* - `recipient`, if a contract address, is this contract's own address.
|
|
237
253
|
*
|
|
238
254
|
* @param {Bytes<32>} domain - 32-byte token discriminator.
|
|
239
|
-
* @param {Either<ZswapCoinPublicKey, ContractAddress>} recipient - The coin
|
|
255
|
+
* @param {Either<ZswapCoinPublicKey, ContractAddress>} recipient - The coin
|
|
256
|
+
* recipient: any coin public key, or this contract's own address.
|
|
240
257
|
* @param {Uint<64>} amount - Quantity to mint. Capped at `Uint<64>` by the protocol.
|
|
241
258
|
* @param {Bytes<32>} nonce - Caller-supplied nonce. Must be unique per (domain, contract).
|
|
242
259
|
* @return {ShieldedCoinInfo} - The newly created coin's info (nonce, color, value).
|
|
@@ -248,9 +265,16 @@ module NativeShieldedTokenCore {
|
|
|
248
265
|
nonce: Bytes<32>
|
|
249
266
|
): ShieldedCoinInfo {
|
|
250
267
|
assertInitialized();
|
|
268
|
+
const self = kernel.self();
|
|
251
269
|
assert(!Utils_isKeyOrAddressZero(recipient), "NativeShieldedToken: invalid recipient");
|
|
270
|
+
assert(recipient.is_left || recipient.right == self, "NativeShieldedToken: recipient contract must be self");
|
|
252
271
|
|
|
253
|
-
|
|
272
|
+
const coin = mintShieldedToken(disclose(domain), disclose(amount), disclose(nonce), disclose(recipient));
|
|
273
|
+
if (disclose(!recipient.is_left)) {
|
|
274
|
+
receiveShielded(coin);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return coin;
|
|
254
278
|
}
|
|
255
279
|
|
|
256
280
|
/**
|
|
@@ -265,13 +289,14 @@ module NativeShieldedTokenCore {
|
|
|
265
289
|
* @dev The coin is received by the contract and spent in the same
|
|
266
290
|
* transaction, so the spend goes through `sendImmediateShielded` (the
|
|
267
291
|
* transient path). For coins the contract already holds, use
|
|
268
|
-
* `_burnFromSelf` instead.
|
|
292
|
+
* `_burnFromSelf` instead. A `right(kernel.self())` refund is claimed via
|
|
293
|
+
* `receiveShielded` in this same call.
|
|
269
294
|
*
|
|
270
295
|
* @notice The returned refund coin info is the only copy available to
|
|
271
296
|
* `refundTo`; callers SHOULD deliver it out of band. Wallets cannot detect
|
|
272
297
|
* contract-sent coins by scanning the chain.
|
|
273
298
|
*
|
|
274
|
-
* @constraints k=16, rows=
|
|
299
|
+
* @constraints k=16, rows=53639
|
|
275
300
|
*
|
|
276
301
|
* Requirements:
|
|
277
302
|
*
|
|
@@ -280,12 +305,14 @@ module NativeShieldedTokenCore {
|
|
|
280
305
|
* - `amount` is less than or equal to `coin.value`.
|
|
281
306
|
* - `refundTo` is not zero (the zero key is the burn address; a zero
|
|
282
307
|
* `refundTo` would silently burn the change as well).
|
|
308
|
+
* - `refundTo`, if a contract address, is this contract's own address.
|
|
283
309
|
*
|
|
284
310
|
* @param {Bytes<32>} domain - 32-byte token discriminator.
|
|
285
311
|
* @param {ShieldedCoinInfo} coin - The coin to burn from.
|
|
286
312
|
* @param {Uint<128>} amount - Value to destroy. Must be <= `coin.value`.
|
|
287
313
|
* @param {Either<ZswapCoinPublicKey, ContractAddress>} refundTo - Where to
|
|
288
|
-
* route the unspent portion (`coin.value - amount`)
|
|
314
|
+
* route the unspent portion (`coin.value - amount`): any coin public key, or
|
|
315
|
+
* this contract's own address.
|
|
289
316
|
* @return {Maybe<ShieldedCoinInfo>} - The refund coin created for `refundTo`,
|
|
290
317
|
* or `none` if the coin was burned in full.
|
|
291
318
|
*/
|
|
@@ -296,9 +323,11 @@ module NativeShieldedTokenCore {
|
|
|
296
323
|
refundTo: Either<ZswapCoinPublicKey, ContractAddress>
|
|
297
324
|
): Maybe<ShieldedCoinInfo> {
|
|
298
325
|
assertInitialized();
|
|
299
|
-
|
|
326
|
+
const self = kernel.self();
|
|
327
|
+
assert(coin.color == tokenType(disclose(domain), self), "NativeShieldedToken: wrong token");
|
|
300
328
|
assert(coin.value >= amount, "NativeShieldedToken: insufficient coin value");
|
|
301
329
|
assert(!Utils_isKeyOrAddressZero(refundTo), "NativeShieldedToken: invalid refund target");
|
|
330
|
+
assert(refundTo.is_left || refundTo.right == self, "NativeShieldedToken: refund contract must be self");
|
|
302
331
|
|
|
303
332
|
receiveShielded(disclose(coin));
|
|
304
333
|
const sendRes = sendImmediateShielded(disclose(coin), shieldedBurnAddress(), disclose(amount));
|
|
@@ -309,6 +338,9 @@ module NativeShieldedTokenCore {
|
|
|
309
338
|
disclose(refundTo),
|
|
310
339
|
disclose(sendRes.change.value.value)
|
|
311
340
|
);
|
|
341
|
+
if (disclose(!refundTo.is_left)) {
|
|
342
|
+
receiveShielded(refundRes.sent);
|
|
343
|
+
}
|
|
312
344
|
return some<ShieldedCoinInfo>(refundRes.sent);
|
|
313
345
|
}
|
|
314
346
|
return none<ShieldedCoinInfo>();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (token/NativeShieldedTokenFamily.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -26,6 +26,10 @@ pragma language_version >= 0.26.0;
|
|
|
26
26
|
* set of core state (a single init flag and one name/symbol/decimals).
|
|
27
27
|
* Pick one flavor per contract.
|
|
28
28
|
*
|
|
29
|
+
* @notice Recipients must be coin public keys: contract-addressed recipients
|
|
30
|
+
* are not supported at this layer. For a coin the contract holds itself, use
|
|
31
|
+
* `_mintToSelf`, which mints to `kernel.self()` and claims it in the same call.
|
|
32
|
+
*
|
|
29
33
|
* @notice This module exposes composable building blocks for minting and
|
|
30
34
|
* burning native shielded coins. It does NOT include access control: consuming
|
|
31
35
|
* contracts compose that via the module/contract pattern (Ownable,
|
|
@@ -186,7 +190,7 @@ module NativeShieldedTokenFamily {
|
|
|
186
190
|
* recipient; callers SHOULD deliver it out of band. Wallets cannot detect
|
|
187
191
|
* contract-minted coins by scanning the chain.
|
|
188
192
|
*
|
|
189
|
-
* @constraints k=14, rows=
|
|
193
|
+
* @constraints k=14, rows=10727
|
|
190
194
|
*
|
|
191
195
|
* Requirements:
|
|
192
196
|
*
|
|
@@ -195,18 +199,59 @@ module NativeShieldedTokenFamily {
|
|
|
195
199
|
*
|
|
196
200
|
* @param {Bytes<32>} domain - 32-byte token discriminator. Same domain + same
|
|
197
201
|
* contract address produces the same coin color (i.e. same token type).
|
|
198
|
-
* @param {
|
|
202
|
+
* @param {ZswapCoinPublicKey} recipient - The coin recipient.
|
|
199
203
|
* @param {Uint<64>} amount - Quantity to mint. Capped at `Uint<64>` by the protocol.
|
|
200
204
|
* @param {Bytes<32>} nonce - Caller-supplied nonce. Must be unique per (domain, contract).
|
|
201
205
|
* @return {ShieldedCoinInfo} - The newly created coin's info (nonce, color, value).
|
|
202
206
|
*/
|
|
203
207
|
export circuit _mint(
|
|
204
208
|
domain: Bytes<32>,
|
|
205
|
-
recipient:
|
|
209
|
+
recipient: ZswapCoinPublicKey,
|
|
210
|
+
amount: Uint<64>,
|
|
211
|
+
nonce: Bytes<32>
|
|
212
|
+
): ShieldedCoinInfo {
|
|
213
|
+
return Core__mint(
|
|
214
|
+
domain,
|
|
215
|
+
left<ZswapCoinPublicKey, ContractAddress>(recipient),
|
|
216
|
+
amount,
|
|
217
|
+
nonce
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* @description Mints `amount` of the token identified by `domain` to this
|
|
223
|
+
* contract itself, claiming the coin in the same call. Forwards to
|
|
224
|
+
* `NativeShieldedTokenCore._mint` with `right(kernel.self())`.
|
|
225
|
+
*
|
|
226
|
+
* @dev Nonce uniqueness is the caller's responsibility, as in `_mint`. Spend
|
|
227
|
+
* the coin later with `_burnFromSelf`, once it carries an `mt_index`.
|
|
228
|
+
*
|
|
229
|
+
* @notice The consumer SHOULD persist the returned coin info in its own
|
|
230
|
+
* ledger state: it is the contract's holding and is not otherwise
|
|
231
|
+
* recoverable.
|
|
232
|
+
*
|
|
233
|
+
* @constraints k=14, rows=16309
|
|
234
|
+
*
|
|
235
|
+
* Requirements:
|
|
236
|
+
*
|
|
237
|
+
* - Contract is initialized.
|
|
238
|
+
*
|
|
239
|
+
* @param {Bytes<32>} domain - 32-byte token discriminator.
|
|
240
|
+
* @param {Uint<64>} amount - Quantity to mint. Capped at `Uint<64>` by the protocol.
|
|
241
|
+
* @param {Bytes<32>} nonce - Caller-supplied nonce. Must be unique per (domain, contract).
|
|
242
|
+
* @return {ShieldedCoinInfo} - The newly created coin's info (nonce, color, value).
|
|
243
|
+
*/
|
|
244
|
+
export circuit _mintToSelf(
|
|
245
|
+
domain: Bytes<32>,
|
|
206
246
|
amount: Uint<64>,
|
|
207
247
|
nonce: Bytes<32>
|
|
208
248
|
): ShieldedCoinInfo {
|
|
209
|
-
return Core__mint(
|
|
249
|
+
return Core__mint(
|
|
250
|
+
domain,
|
|
251
|
+
right<ZswapCoinPublicKey, ContractAddress>(kernel.self()),
|
|
252
|
+
amount,
|
|
253
|
+
nonce
|
|
254
|
+
);
|
|
210
255
|
}
|
|
211
256
|
|
|
212
257
|
/**
|
|
@@ -227,7 +272,7 @@ module NativeShieldedTokenFamily {
|
|
|
227
272
|
* `refundTo`; callers SHOULD deliver it out of band. Wallets cannot detect
|
|
228
273
|
* contract-sent coins by scanning the chain.
|
|
229
274
|
*
|
|
230
|
-
* @constraints k=16, rows=
|
|
275
|
+
* @constraints k=16, rows=41603
|
|
231
276
|
*
|
|
232
277
|
* Requirements:
|
|
233
278
|
*
|
|
@@ -240,8 +285,8 @@ module NativeShieldedTokenFamily {
|
|
|
240
285
|
* @param {Bytes<32>} domain - 32-byte token discriminator.
|
|
241
286
|
* @param {ShieldedCoinInfo} coin - The coin to burn from.
|
|
242
287
|
* @param {Uint<128>} amount - Value to destroy. Must be <= `coin.value`.
|
|
243
|
-
* @param {
|
|
244
|
-
*
|
|
288
|
+
* @param {ZswapCoinPublicKey} refundTo - Where to route the unspent
|
|
289
|
+
* portion (`coin.value - amount`).
|
|
245
290
|
* @return {Maybe<ShieldedCoinInfo>} - The refund coin created for `refundTo`,
|
|
246
291
|
* or `none` if the coin was burned in full.
|
|
247
292
|
*/
|
|
@@ -249,9 +294,14 @@ module NativeShieldedTokenFamily {
|
|
|
249
294
|
domain: Bytes<32>,
|
|
250
295
|
coin: ShieldedCoinInfo,
|
|
251
296
|
amount: Uint<128>,
|
|
252
|
-
refundTo:
|
|
297
|
+
refundTo: ZswapCoinPublicKey
|
|
253
298
|
): Maybe<ShieldedCoinInfo> {
|
|
254
|
-
return Core__burn(
|
|
299
|
+
return Core__burn(
|
|
300
|
+
domain,
|
|
301
|
+
coin,
|
|
302
|
+
amount,
|
|
303
|
+
left<ZswapCoinPublicKey, ContractAddress>(refundTo)
|
|
304
|
+
);
|
|
255
305
|
}
|
|
256
306
|
|
|
257
307
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (token/NonFungibleToken.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -58,7 +58,7 @@ pragma language_version >= 0.26.0;
|
|
|
58
58
|
* or in ledger writes. Canonicalization zeroes out the inactive branch of the Either,
|
|
59
59
|
* ensuring that two values with the same active branch always resolve to the same map key
|
|
60
60
|
* regardless of what data the inactive branch carries. Write paths are canonicalized in
|
|
61
|
-
* `_update` (for `_owners` and `_balances`), `
|
|
61
|
+
* `_update` (for `_owners` and `_balances`), `_unsafeApprove` (for `_tokenApprovals`), and
|
|
62
62
|
* `_setApprovalForAll` (for `_operatorApprovals`). Read paths are canonicalized in
|
|
63
63
|
* `balanceOf`, `isApprovedForAll`, and `_isAuthorized`.
|
|
64
64
|
*
|
|
@@ -343,7 +343,7 @@ module NonFungibleToken {
|
|
|
343
343
|
* In the case of an external (non-contract) caller, the caller's identity is derived from the `wit_NonFungibleTokenSK`
|
|
344
344
|
* witness as `persistentHash(secretKey)`.
|
|
345
345
|
*
|
|
346
|
-
* @constraints k=13, rows=
|
|
346
|
+
* @constraints k=13, rows=3406
|
|
347
347
|
*
|
|
348
348
|
* Requirements:
|
|
349
349
|
*
|
|
@@ -444,7 +444,7 @@ module NonFungibleToken {
|
|
|
444
444
|
* In the case of an external (non-contract) caller, the caller's identity is derived from the `wit_NonFungibleTokenSK`
|
|
445
445
|
* witness as `persistentHash(secretKey)`.
|
|
446
446
|
*
|
|
447
|
-
* @constraints k=13, rows=
|
|
447
|
+
* @constraints k=13, rows=4702
|
|
448
448
|
*
|
|
449
449
|
* Requirements:
|
|
450
450
|
*
|
|
@@ -482,7 +482,7 @@ module NonFungibleToken {
|
|
|
482
482
|
* are not currently supported. Tokens sent to a contract address may become irretrievable.
|
|
483
483
|
* Once contract-to-contract calls are supported, this circuit may be deprecated.
|
|
484
484
|
*
|
|
485
|
-
* @constraints k=13, rows=
|
|
485
|
+
* @constraints k=13, rows=4699
|
|
486
486
|
*
|
|
487
487
|
* Requirements:
|
|
488
488
|
*
|
|
@@ -504,11 +504,14 @@ module NonFungibleToken {
|
|
|
504
504
|
): [] {
|
|
505
505
|
assertInitialized();
|
|
506
506
|
assert(!Utils_isTargetZero(to), "NonFungibleToken: invalid receiver");
|
|
507
|
-
// Setting an "auth" argument enables the `_isAuthorized` check which verifies that the token exists
|
|
508
|
-
// (fromAddress != 0). Therefore, it is not needed to verify that the return value is not 0 here.
|
|
509
507
|
const auth = left<Bytes<32>, ContractAddress>(_computeAccountId());
|
|
510
508
|
const previousOwner = _update(to, tokenId, auth);
|
|
511
509
|
|
|
510
|
+
// The `_isAuthorized` check inside `_update` already implies the token exists, but that
|
|
511
|
+
// holds only while approvals are never recorded for unminted tokens. Assert it directly
|
|
512
|
+
// so a misused `_unsafeApprove` cannot turn this circuit into an unauthorized mint.
|
|
513
|
+
assert(!Utils_isTargetZero(previousOwner), "NonFungibleToken: nonexistent token");
|
|
514
|
+
|
|
512
515
|
const canonFrom = Utils_canonicalize<Bytes<32>, ContractAddress>(fromAddress);
|
|
513
516
|
assert(previousOwner == canonFrom, "NonFungibleToken: incorrect owner");
|
|
514
517
|
}
|
|
@@ -648,8 +651,8 @@ module NonFungibleToken {
|
|
|
648
651
|
|
|
649
652
|
// Execute the update
|
|
650
653
|
if (!Utils_isTargetZero(disclose(fromAddress))) {
|
|
651
|
-
// Clear approval. No need to re-authorize
|
|
652
|
-
|
|
654
|
+
// Clear approval. No need to re-authorize or re-read the owner
|
|
655
|
+
_unsafeApprove(Utils_zeroAccount(), tokenId, Utils_zeroAccount(), false);
|
|
653
656
|
const canonFrom = Utils_canonicalize<Bytes<32>, ContractAddress>(fromAddress);
|
|
654
657
|
const newBalance = _balances.lookup(disclose(canonFrom)) - 1 as Uint<128>;
|
|
655
658
|
_balances.insert(disclose(canonFrom), disclose(newBalance));
|
|
@@ -820,11 +823,12 @@ module NonFungibleToken {
|
|
|
820
823
|
/**
|
|
821
824
|
* @description Approve `to` to operate on `tokenId`.
|
|
822
825
|
*
|
|
823
|
-
* @constraints k=11, rows=
|
|
826
|
+
* @constraints k=11, rows=1755
|
|
824
827
|
*
|
|
825
828
|
* Requirements:
|
|
826
829
|
*
|
|
827
830
|
* - The contract is initialized.
|
|
831
|
+
* - `tokenId` must exist.
|
|
828
832
|
* - If `auth` is non 0, then this function will check that `auth` is either the owner of the token,
|
|
829
833
|
* or approved to operate on the token (by the owner).
|
|
830
834
|
*
|
|
@@ -838,6 +842,43 @@ module NonFungibleToken {
|
|
|
838
842
|
tokenId: Uint<128>,
|
|
839
843
|
auth: Either<Bytes<32>, ContractAddress>
|
|
840
844
|
): [] {
|
|
845
|
+
_unsafeApprove(to, tokenId, auth, true);
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* @description Approve `to` to operate on `tokenId`, requiring the token to exist
|
|
850
|
+
* only when `isExistenceRequired` is true.
|
|
851
|
+
*
|
|
852
|
+
* @constraints k=11, rows=1868
|
|
853
|
+
*
|
|
854
|
+
* @warning Passing false skips the check that `tokenId` was minted. Both
|
|
855
|
+
* `_unsafeTransferFrom` and `_update` read that invariant back, so a planted approval
|
|
856
|
+
* can mint a token nobody authorized or outlive a later mint. Pass false only where
|
|
857
|
+
* the owner has already been read, as `_update` does.
|
|
858
|
+
*
|
|
859
|
+
* @dev Counterpart to Solidity's `_approve(to, tokenId, auth, bool emitEvent)`, where
|
|
860
|
+
* the flag also suppresses the `Approval` event. Compact has no events, so it carries
|
|
861
|
+
* the existence check alone.
|
|
862
|
+
*
|
|
863
|
+
* Requirements:
|
|
864
|
+
*
|
|
865
|
+
* - The contract is initialized.
|
|
866
|
+
* - `tokenId` must exist, unless `isExistenceRequired` is false and `auth` is zero.
|
|
867
|
+
* - If `auth` is non 0, then this function will check that `auth` is either the owner of the token,
|
|
868
|
+
* or approved to operate on the token (by the owner).
|
|
869
|
+
*
|
|
870
|
+
* @param {Either<Bytes<32>, ContractAddress>} to - The target account to approve
|
|
871
|
+
* @param {Uint<128>} tokenId - The token to approve
|
|
872
|
+
* @param {Either<Bytes<32>, ContractAddress>} auth - An account authorized to operate on all tokens held by the owner of the token
|
|
873
|
+
* @param {Boolean} isExistenceRequired - Whether `tokenId` must exist
|
|
874
|
+
* @return {[]} - Empty tuple.
|
|
875
|
+
*/
|
|
876
|
+
export circuit _unsafeApprove(
|
|
877
|
+
to: Either<Bytes<32>, ContractAddress>,
|
|
878
|
+
tokenId: Uint<128>,
|
|
879
|
+
auth: Either<Bytes<32>, ContractAddress>,
|
|
880
|
+
isExistenceRequired: Boolean
|
|
881
|
+
): [] {
|
|
841
882
|
assertInitialized();
|
|
842
883
|
// Canonicalize + normalize `to`
|
|
843
884
|
const canonTo = Utils_canonicalize<Bytes<32>, ContractAddress>(to);
|
|
@@ -846,11 +887,14 @@ module NonFungibleToken {
|
|
|
846
887
|
// Canonicalize auth
|
|
847
888
|
const canonAuth = Utils_canonicalize<Bytes<32>, ContractAddress>(auth);
|
|
848
889
|
|
|
849
|
-
|
|
890
|
+
// Avoid reading the owner unless necessary
|
|
891
|
+
if (disclose(isExistenceRequired) || !Utils_isTargetZero(disclose(canonAuth))) {
|
|
850
892
|
const owner = _requireOwned(tokenId);
|
|
851
893
|
|
|
852
894
|
// We do not use _isAuthorized because single-token approvals should not be able to call approve
|
|
853
|
-
assert((
|
|
895
|
+
assert((Utils_isTargetZero(disclose(canonAuth)) ||
|
|
896
|
+
owner == disclose(canonAuth) ||
|
|
897
|
+
isApprovedForAll(owner, canonAuth)),
|
|
854
898
|
"NonFungibleToken: invalid approver"
|
|
855
899
|
);
|
|
856
900
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (token/extensions/ConfidentialFungibleTokenPublicSupply.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (token/extensions/NativeShieldedTokenDerivedNonce.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -20,7 +20,7 @@ pragma language_version >= 0.26.0;
|
|
|
20
20
|
*
|
|
21
21
|
* export circuit mint(
|
|
22
22
|
* domain: Bytes<32>,
|
|
23
|
-
* recipient:
|
|
23
|
+
* recipient: ZswapCoinPublicKey,
|
|
24
24
|
* amount: Uint<64>,
|
|
25
25
|
* nonce: Bytes<32>
|
|
26
26
|
* ): ShieldedCoinInfo {
|
|
@@ -33,7 +33,7 @@ pragma language_version >= 0.26.0;
|
|
|
33
33
|
* domain: Bytes<32>,
|
|
34
34
|
* coin: ShieldedCoinInfo,
|
|
35
35
|
* amount: Uint<128>,
|
|
36
|
-
* refundTo:
|
|
36
|
+
* refundTo: ZswapCoinPublicKey
|
|
37
37
|
* ): Maybe<ShieldedCoinInfo> {
|
|
38
38
|
* const refund = Family__burn(domain, coin, amount, refundTo);
|
|
39
39
|
* Supply__addBurned(domain, amount);
|
|
@@ -18,7 +18,7 @@ pragma language_version >= 0.26.0;
|
|
|
18
18
|
* pieces, calling the accounting block alongside the matching token op:
|
|
19
19
|
*
|
|
20
20
|
* export circuit mint(
|
|
21
|
-
* recipient:
|
|
21
|
+
* recipient: ZswapCoinPublicKey,
|
|
22
22
|
* amount: Uint<64>,
|
|
23
23
|
* nonce: Bytes<32>
|
|
24
24
|
* ): ShieldedCoinInfo {
|
|
@@ -30,7 +30,7 @@ pragma language_version >= 0.26.0;
|
|
|
30
30
|
* export circuit burn(
|
|
31
31
|
* coin: ShieldedCoinInfo,
|
|
32
32
|
* amount: Uint<128>,
|
|
33
|
-
* refundTo:
|
|
33
|
+
* refundTo: ZswapCoinPublicKey
|
|
34
34
|
* ): Maybe<ShieldedCoinInfo> {
|
|
35
35
|
* const refund = Token__burn(coin, amount, refundTo);
|
|
36
36
|
* Supply__addBurned(amount);
|
package/utils/EvmAbi.compact
CHANGED
package/utils/Utils.compact
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (utils/Utils.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -150,6 +150,16 @@ module Utils {
|
|
|
150
150
|
* ## ID Derivation
|
|
151
151
|
* `accountId = persistentHash(secretKey)`
|
|
152
152
|
*
|
|
153
|
+
* @dev The absence of a domain-separation tag is DELIBERATE. This identifier
|
|
154
|
+
* is global by design: the same key material yields the same identity in
|
|
155
|
+
* every module deriving one, so a user who wishes to carry one identity
|
|
156
|
+
* across modules can. Modules wanting a per-deployment, unlinkable identity
|
|
157
|
+
* should not use this circuit.
|
|
158
|
+
*
|
|
159
|
+
* @dev NOT FOR PRIVATE DERIVATION. This returns an identifier, not a secret,
|
|
160
|
+
* and the construction is untagged. A circuit deriving a PRIVATE value from a
|
|
161
|
+
* secret MUST use its own domain-separation tag.
|
|
162
|
+
*
|
|
153
163
|
* @param {Bytes<32>} secretKey - A 32-byte cryptographically secure random value.
|
|
154
164
|
*
|
|
155
165
|
* @returns {Bytes<32>} accountId - The computed account identifier.
|