@openzeppelin/compact-contracts 0.4.0-alpha.5 → 0.4.0
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/README.md +1 -1
- package/access/AccessControl.compact +1 -1
- package/access/Ownable.compact +1 -3
- package/access/ShieldedAccessControl.compact +44 -41
- package/access/ZOwnablePK.compact +12 -5
- package/crypto/EcdhMask.compact +11 -1
- package/crypto/Ecdsa.compact +1 -1
- package/crypto/Eip712.compact +1 -1
- package/crypto/ElGamal.compact +1 -1
- package/multisig/ForwarderPrivate.compact +17 -6
- package/multisig/ForwarderShielded.compact +1 -1
- package/multisig/ForwarderUnshielded.compact +1 -1
- package/multisig/ProposalManager.compact +65 -127
- package/multisig/RecipientTypes.compact +48 -0
- package/multisig/Secp256k1EcdsaMultisig.compact +275 -0
- package/multisig/ShieldedTreasury.compact +20 -8
- package/multisig/ShieldedTreasuryStateless.compact +11 -5
- package/multisig/Signer.compact +1 -1
- package/multisig/UnshieldedTreasury.compact +24 -11
- package/multisig/examples/ForwarderPrivateExample.compact +3 -2
- package/multisig/examples/ForwarderShieldedExample.compact +1 -1
- package/multisig/examples/ForwarderUnshieldedExample.compact +1 -1
- package/multisig/examples/NativeShieldedTokenIssuerExample.compact +4 -4
- package/multisig/examples/ShieldedMultiSigV2Example.compact +7 -9
- package/multisig/presets/NativeShieldedTokenIssuer.compact +88 -84
- package/multisig/presets/ShieldedMultiSigV2.compact +50 -52
- package/package.json +1 -1
- package/security/Allowlist.compact +1 -1
- package/security/Blocklist.compact +1 -1
- package/security/Initializable.compact +1 -3
- package/security/Pausable.compact +1 -1
- package/token/ConfidentialFungibleToken.compact +70 -22
- package/token/FungibleToken.compact +1 -3
- package/token/MultiToken.compact +1 -3
- package/token/NativeShieldedToken.compact +11 -3
- package/token/NativeShieldedTokenCore.compact +1 -1
- package/token/NativeShieldedTokenFamily.compact +1 -1
- package/token/NonFungibleToken.compact +1 -3
- package/token/examples/ZOwnableNativeShieldedTokenExample.compact +109 -0
- package/token/extensions/ConfidentialFungibleTokenPublicSupply.compact +1 -1
- package/token/extensions/NativeShieldedTokenDerivedNonce.compact +1 -1
- package/token/presets/ZOwnableNativeShieldedToken.compact +314 -0
- package/utils/EvmAbi.compact +1 -1
- package/utils/Utils.compact +1 -1
- package/multisig/EcdsaSignerManager.compact +0 -248
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0 (multisig/presets/ShieldedMultiSigV2.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @module ShieldedMultiSigV2
|
|
8
|
-
* @description Privacy-preserving
|
|
8
|
+
* @description Privacy-preserving threshold multisig contract.
|
|
9
9
|
*
|
|
10
10
|
* Signer identities are stored as commitments: hashes of ECDSA public
|
|
11
11
|
* keys combined with an instance salt and domain separator. Signature
|
|
@@ -14,32 +14,41 @@ pragma language_version >= 0.26.0;
|
|
|
14
14
|
* and replay protection. All other coordination (signature collection,
|
|
15
15
|
* coin selection) happens off-chain.
|
|
16
16
|
*
|
|
17
|
+
* `t` is the approval width and the threshold: `execute` verifies exactly
|
|
18
|
+
* `t` distinct signers. Import as `"../presets/ShieldedMultiSigV2"<t>`; the
|
|
19
|
+
* implementing contract fixes the signer count `n` at `initialize`. Import
|
|
20
|
+
* one width per contract: two widths share one signer registry, see
|
|
21
|
+
* `Secp256k1EcdsaMultisig`.
|
|
22
|
+
*
|
|
17
23
|
* Treasury is fully stateless meaning coin data is not stored on the public ledger.
|
|
18
24
|
* Deposits call receiveShielded only. The operator discovers coin indices
|
|
19
25
|
* through ZswapOutput events from the indexer, constructs QualifiedShieldedCoinInfo
|
|
20
26
|
* off-chain, and provides it as a circuit parameter for spending.
|
|
21
27
|
*
|
|
28
|
+
* @notice Keeping coin data off the ledger hides balances from the public,
|
|
29
|
+
* not from a depositor. Whoever knows a deposited coin can find the `execute`
|
|
30
|
+
* that spends it, recover the amount sent, test candidate recipients against
|
|
31
|
+
* the sent coin's commitment, and derive the change coin, so every later
|
|
32
|
+
* spend descending from that change and the balance it carries are traceable
|
|
33
|
+
* by that depositor. See `ShieldedTreasuryStateless` for the derivation.
|
|
34
|
+
*
|
|
22
35
|
* @notice Requires ZKIR v3: `keccak256` is unavailable on the v2 backend.
|
|
23
36
|
*
|
|
24
37
|
* @notice Implementing contracts register the signer set from their
|
|
25
38
|
* constructor by calling this module's `initialize`, and MUST NOT import
|
|
26
|
-
* `
|
|
39
|
+
* `Signer` or `Secp256k1EcdsaMultisig` directly.
|
|
27
40
|
*/
|
|
28
|
-
module ShieldedMultiSigV2 {
|
|
41
|
+
module ShieldedMultiSigV2<#t> {
|
|
29
42
|
import CompactStandardLibrary;
|
|
30
43
|
|
|
31
|
-
import "../
|
|
44
|
+
import "../Secp256k1EcdsaMultisig"<t> prefix Secp256k1EcdsaMultisig_;
|
|
32
45
|
import "../../crypto/Eip712" prefix Eip712_;
|
|
33
46
|
import "../../utils/EvmAbi" prefix EvmAbi_;
|
|
34
|
-
import "../
|
|
47
|
+
import "../RecipientTypes";
|
|
35
48
|
import "../ShieldedTreasuryStateless" prefix Treasury_;
|
|
36
49
|
|
|
37
|
-
// Implementing contracts need
|
|
38
|
-
|
|
39
|
-
// unwritten copy of its state.
|
|
40
|
-
export { Proposal_Recipient };
|
|
41
|
-
|
|
42
|
-
// ─── State ──────────────────────────────────────────────────────
|
|
50
|
+
// Implementing contracts need these for the re-exported `execute` signature.
|
|
51
|
+
export { Recipient, RecipientKind };
|
|
43
52
|
|
|
44
53
|
/**
|
|
45
54
|
* @description Monotonic operation counter. `execute` reads it as that
|
|
@@ -54,10 +63,8 @@ module ShieldedMultiSigV2 {
|
|
|
54
63
|
*/
|
|
55
64
|
export sealed ledger _domainSeparator: Bytes<32>;
|
|
56
65
|
|
|
57
|
-
// ─── Initialization ─────────────────────────────────────────────
|
|
58
|
-
|
|
59
66
|
/**
|
|
60
|
-
* @description Registers the signer set
|
|
67
|
+
* @description Registers the signer set at threshold `t` and fixes the
|
|
61
68
|
* EIP-712 domain separator.
|
|
62
69
|
*
|
|
63
70
|
* @notice Call from the implementing contract's constructor only. It writes
|
|
@@ -82,19 +89,17 @@ module ShieldedMultiSigV2 {
|
|
|
82
89
|
*
|
|
83
90
|
* - `instanceSalt` should be cryptographically random.
|
|
84
91
|
* - `signerCommitments` must not contain duplicates.
|
|
85
|
-
* - `
|
|
92
|
+
* - `n` must be at least `t`.
|
|
86
93
|
*
|
|
87
94
|
* @param {Bytes<32>} instanceSalt - Per-deployment salt for commitment derivation.
|
|
88
|
-
* @param {Vector<
|
|
89
|
-
* @param {Uint<8>} thresh - Approvals required. Must be 2.
|
|
95
|
+
* @param {Vector<n, Bytes<32>>} signerCommitments - Hashed signer identities.
|
|
90
96
|
* @returns {[]} Empty tuple.
|
|
91
97
|
*/
|
|
92
|
-
export circuit initialize(
|
|
98
|
+
export circuit initialize<#n>(
|
|
93
99
|
instanceSalt: Bytes<32>,
|
|
94
|
-
signerCommitments: Vector<
|
|
95
|
-
thresh: Uint<8>
|
|
100
|
+
signerCommitments: Vector<n, Bytes<32>>
|
|
96
101
|
): [] {
|
|
97
|
-
|
|
102
|
+
Secp256k1EcdsaMultisig_initialize<n>(instanceSalt, signerCommitments);
|
|
98
103
|
|
|
99
104
|
const hashedName = keccak256<Bytes<18>>(pad(18, "ShieldedMultiSigV2"));
|
|
100
105
|
const hashedVersion = keccak256<Bytes<1>>(pad(1, "1"));
|
|
@@ -127,14 +132,13 @@ module ShieldedMultiSigV2 {
|
|
|
127
132
|
return typeHash as Bytes<32>;
|
|
128
133
|
}
|
|
129
134
|
|
|
130
|
-
// ─── Deposit ────────────────────────────────────────────────────
|
|
131
|
-
|
|
132
135
|
/**
|
|
133
136
|
* @description Receives a shielded coin into the multisig treasury.
|
|
134
137
|
*
|
|
135
138
|
* No access control which allows anyone to deposit. The coin is claimed at the
|
|
136
139
|
* protocol level through receiveShielded. No coin data is stored on the
|
|
137
|
-
* public ledger,
|
|
140
|
+
* public ledger, so no balance is readable from it; a depositor can still
|
|
141
|
+
* follow the coin they deposited (see the module notice).
|
|
138
142
|
*
|
|
139
143
|
* The operator discovers the coin's Merkle tree index by subscribing
|
|
140
144
|
* to ZswapOutput events via the indexer, filtering by contract address,
|
|
@@ -149,8 +153,6 @@ module ShieldedMultiSigV2 {
|
|
|
149
153
|
receiveShielded(disclose(coin));
|
|
150
154
|
}
|
|
151
155
|
|
|
152
|
-
// ─── Execute ────────────────────────────────────────────────────
|
|
153
|
-
|
|
154
156
|
/**
|
|
155
157
|
* @description Executes a shielded send authorized by threshold signatures.
|
|
156
158
|
*
|
|
@@ -161,38 +163,38 @@ module ShieldedMultiSigV2 {
|
|
|
161
163
|
* separator. The digest is bound to the contract instance and the full recipient (kind and
|
|
162
164
|
* address), so a signature authorizes exactly one operation on one instance.
|
|
163
165
|
*
|
|
164
|
-
* Approvals are checked by `
|
|
165
|
-
* commitment from their public key and the instance salt
|
|
166
|
-
*
|
|
166
|
+
* Approvals are checked by `Secp256k1EcdsaMultisig`, which derives each
|
|
167
|
+
* signer's commitment from their public key and the instance salt and
|
|
168
|
+
* rejects duplicates. Constraints below are measured at `t = 2`.
|
|
167
169
|
*
|
|
168
170
|
* @notice `to` must be a `ShieldedUser`. A contract-addressed coin would be
|
|
169
171
|
* unclaimable, making the transaction malformed.
|
|
170
172
|
*
|
|
171
|
-
* @constraints k=17, rows=
|
|
173
|
+
* @constraints k=17, rows=98969 (zkir-v3)
|
|
172
174
|
*
|
|
173
175
|
* Requirements:
|
|
174
176
|
*
|
|
175
|
-
* -
|
|
176
|
-
* -
|
|
177
|
+
* - No two entries may be the same signer.
|
|
178
|
+
* - Every public key must hash to a registered signer commitment.
|
|
179
|
+
* - Every signature must be valid over the message hash and use the low-s
|
|
177
180
|
* encoding.
|
|
178
|
-
* - Signers must not be duplicates.
|
|
179
181
|
* - `to.kind` must be `ShieldedUser`.
|
|
180
182
|
* - Coin value must be >= amount.
|
|
181
183
|
*
|
|
182
|
-
* @param {
|
|
184
|
+
* @param {Recipient} to - The recipient.
|
|
183
185
|
* @param {Uint<128>} amount - The amount to send.
|
|
184
186
|
* @param {QualifiedShieldedCoinInfo} coin - The coin to spend (from operator's pool).
|
|
185
|
-
* @param {Vector<
|
|
186
|
-
* @param {Vector<
|
|
187
|
+
* @param {Vector<t, Secp256k1Point>} pubkeys - Public keys of approving signers.
|
|
188
|
+
* @param {Vector<t, Secp256k1EcdsaSignature>} signatures - ECDSA signatures over the operation.
|
|
187
189
|
*
|
|
188
190
|
* @returns {ShieldedSendResult} The send result including any change.
|
|
189
191
|
*/
|
|
190
192
|
export circuit execute(
|
|
191
|
-
to:
|
|
193
|
+
to: Recipient,
|
|
192
194
|
amount: Uint<128>,
|
|
193
195
|
coin: QualifiedShieldedCoinInfo,
|
|
194
|
-
pubkeys: Vector<
|
|
195
|
-
signatures: Vector<
|
|
196
|
+
pubkeys: Vector<t, Secp256k1Point>,
|
|
197
|
+
signatures: Vector<t, Secp256k1EcdsaSignature>
|
|
196
198
|
): ShieldedSendResult {
|
|
197
199
|
// Increment nonce
|
|
198
200
|
const currentNonce = _nonce;
|
|
@@ -212,11 +214,11 @@ module ShieldedMultiSigV2 {
|
|
|
212
214
|
EvmAbi_uint128Word(amount)
|
|
213
215
|
]));
|
|
214
216
|
|
|
215
|
-
|
|
217
|
+
Secp256k1EcdsaMultisig_assertApprovals(msgHash, pubkeys, signatures);
|
|
216
218
|
|
|
217
219
|
assert(
|
|
218
|
-
to.kind ==
|
|
219
|
-
"
|
|
220
|
+
to.kind == RecipientKind.ShieldedUser,
|
|
221
|
+
"ShieldedMultiSigV2: recipient must be a coin public key"
|
|
220
222
|
);
|
|
221
223
|
const recipient = left<ZswapCoinPublicKey, ContractAddress>(
|
|
222
224
|
ZswapCoinPublicKey { bytes: to.address }
|
|
@@ -224,11 +226,9 @@ module ShieldedMultiSigV2 {
|
|
|
224
226
|
return Treasury__send(coin, recipient, amount);
|
|
225
227
|
}
|
|
226
228
|
|
|
227
|
-
// ─── Commitments ────────────────────────────────────────────────
|
|
228
|
-
|
|
229
229
|
/**
|
|
230
230
|
* @description Computes a signer commitment from a secp256k1 public key,
|
|
231
|
-
* as `persistentHash(pkX, pkY, salt, "
|
|
231
|
+
* as `persistentHash(pkX, pkY, salt, "Secp256k1EcdsaMultisig:signer")`.
|
|
232
232
|
*
|
|
233
233
|
* Pure, so the deployer can derive constructor commitments off-chain.
|
|
234
234
|
*
|
|
@@ -245,11 +245,9 @@ module ShieldedMultiSigV2 {
|
|
|
245
245
|
pk: Secp256k1Point,
|
|
246
246
|
salt: Bytes<32>
|
|
247
247
|
): Bytes<32> {
|
|
248
|
-
return
|
|
248
|
+
return Secp256k1EcdsaMultisig_calculateSignerId(pk, salt);
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
// ─── View ───────────────────────────────────────────────────────
|
|
252
|
-
|
|
253
251
|
/**
|
|
254
252
|
* @description Returns the nonce the next `execute` digest will bind to.
|
|
255
253
|
*
|
|
@@ -269,7 +267,7 @@ module ShieldedMultiSigV2 {
|
|
|
269
267
|
* @returns {Uint<8>} The signer count.
|
|
270
268
|
*/
|
|
271
269
|
export circuit getSignerCount(): Uint<8> {
|
|
272
|
-
return
|
|
270
|
+
return Secp256k1EcdsaMultisig_getSignerCount();
|
|
273
271
|
}
|
|
274
272
|
|
|
275
273
|
/**
|
|
@@ -280,7 +278,7 @@ module ShieldedMultiSigV2 {
|
|
|
280
278
|
* @returns {Uint<8>} The threshold.
|
|
281
279
|
*/
|
|
282
280
|
export circuit getThreshold(): Uint<8> {
|
|
283
|
-
return
|
|
281
|
+
return Secp256k1EcdsaMultisig_getThreshold();
|
|
284
282
|
}
|
|
285
283
|
|
|
286
284
|
/**
|
|
@@ -292,6 +290,6 @@ module ShieldedMultiSigV2 {
|
|
|
292
290
|
* @returns {Boolean} True if registered.
|
|
293
291
|
*/
|
|
294
292
|
export circuit isSigner(commitment: Bytes<32>): Boolean {
|
|
295
|
-
return
|
|
293
|
+
return Secp256k1EcdsaMultisig_isSigner(commitment);
|
|
296
294
|
}
|
|
297
295
|
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0 (security/Initializable.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -35,8 +35,6 @@ module Initializable {
|
|
|
35
35
|
/**
|
|
36
36
|
* @description Initializes the state thus ensuring the calling circuit can only be called once.
|
|
37
37
|
*
|
|
38
|
-
* @constraints k=6, rows=28
|
|
39
|
-
*
|
|
40
38
|
* Requirements:
|
|
41
39
|
*
|
|
42
40
|
* - Contract must not be initialized.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0 (token/ConfidentialFungibleToken.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -28,6 +28,16 @@ pragma language_version >= 0.26.0;
|
|
|
28
28
|
* (`extensions/ConfidentialFungibleTokenPublicSupply`) a composing contract pairs
|
|
29
29
|
* with them if it wants a tracked supply.
|
|
30
30
|
*
|
|
31
|
+
* @notice Allowances. `approve` funds the allowance at approve time: `value`
|
|
32
|
+
* moves out of the caller's spendable balance into the escrow, where it stays
|
|
33
|
+
* until spent or re-approved. Funding is required, not a choice: the spender
|
|
34
|
+
* holds no owner encryption key, so at spend time it can only prove against
|
|
35
|
+
* its own escrow copy, never that the owner's balance covers the allowance.
|
|
36
|
+
* An approve conserves the owner's holdings (spendable plus every outstanding
|
|
37
|
+
* escrow), so allowances across spenders can sum to the whole holding but
|
|
38
|
+
* never exceed it, and a re-approve replaces the prior one rather than
|
|
39
|
+
* stacking.
|
|
40
|
+
*
|
|
31
41
|
* @notice Single-receiver. Auditor support, freeze, and admin-style seize are
|
|
32
42
|
* deliberately left to companion modules or a future multi-receiver variant.
|
|
33
43
|
* The escrow-spend primitive here (`_spendEscrow`) enables user-consenting
|
|
@@ -35,6 +45,9 @@ pragma language_version >= 0.26.0;
|
|
|
35
45
|
* requires authority visibility into balances and is therefore out of scope
|
|
36
46
|
* for the single-receiver base.
|
|
37
47
|
*
|
|
48
|
+
* @dev Initialization. Every exported circuit except `initialize` asserts the
|
|
49
|
+
* contract is initialized.
|
|
50
|
+
*
|
|
38
51
|
* @dev Trust model for witnesses.
|
|
39
52
|
*
|
|
40
53
|
* Witness implementations live in the user's wallet (TypeScript frontend) and
|
|
@@ -390,7 +403,9 @@ module ConfidentialFungibleToken {
|
|
|
390
403
|
/**
|
|
391
404
|
* @description Escrowed allowances, keyed by owner then spender. Membership is
|
|
392
405
|
* checked independently of the entry, so an allowance that was never escrowed
|
|
393
|
-
* is unspendable.
|
|
406
|
+
* is unspendable. A spend also requires both owner and spender to be
|
|
407
|
+
* registered, so an entry written here for an unregistered account (for
|
|
408
|
+
* example by a composing contract) is unspendable as well.
|
|
394
409
|
* @type {Bytes<32>} owner - The account that escrowed the allowance.
|
|
395
410
|
* @type {Bytes<32>} spender - The account allowed to spend it.
|
|
396
411
|
* @type {EscrowEntry} entry - The escrowed allowance.
|
|
@@ -618,25 +633,37 @@ module ConfidentialFungibleToken {
|
|
|
618
633
|
|
|
619
634
|
/**
|
|
620
635
|
* @description Returns the escrow entry (the encrypted allowance) that `owner`
|
|
621
|
-
* granted `spender`. When no allowance exists, returns a
|
|
622
|
-
*
|
|
623
|
-
*
|
|
624
|
-
*
|
|
625
|
-
*
|
|
626
|
-
*
|
|
636
|
+
* granted `spender`. When no allowance exists, returns a placeholder entry
|
|
637
|
+
* rather than `default<EscrowEntry>`: the returned Jubjub points are on-curve,
|
|
638
|
+
* so the view is safe to prove (e.g. through a contract-to-contract call),
|
|
639
|
+
* whereas a zeroed default holds off-curve points. The cap is encrypted, not
|
|
640
|
+
* public.
|
|
641
|
+
*
|
|
642
|
+
* @notice The placeholder's `spenderCt` and `ownerCt` are genuine encryptions
|
|
643
|
+
* of 0. Its `ownerMemo` is not: it is a sentinel for an absent allowance,
|
|
644
|
+
* recognised by `ephemeralPk == identity`, which `EcdhMask_encrypt` never
|
|
645
|
+
* produces and `EcdhMask_decrypt` rejects. A wallet must test for the
|
|
646
|
+
* sentinel rather than decrypt and narrow it.
|
|
647
|
+
*
|
|
648
|
+
* @notice "No allowance" and "an allowance of 0" both read as encrypted-zero in
|
|
649
|
+
* the amount fields; the memo sentinel tells them apart, since `approve` stores
|
|
650
|
+
* a real memo even for 0. This getter grants nothing, the spend path
|
|
651
|
+
* (`transferFrom`/`burnFrom`) gates on `_escrow` membership independently, so a
|
|
652
|
+
* non-existent allowance is unspendable.
|
|
653
|
+
*
|
|
654
|
+
* @constraints k=10, rows=938
|
|
627
655
|
*
|
|
628
|
-
*
|
|
629
|
-
* a caller that must distinguish them reads `_escrow` membership off-chain. This
|
|
630
|
-
* getter grants nothing, the spend path (`transferFrom`/`burnFrom`) gates on
|
|
631
|
-
* `_escrow` membership independently, so a non-existent allowance is unspendable.
|
|
656
|
+
* Requirements:
|
|
632
657
|
*
|
|
633
|
-
*
|
|
658
|
+
* - Contract is initialized.
|
|
634
659
|
*
|
|
635
660
|
* @param {Bytes<32>} owner - The account that granted the allowance.
|
|
636
661
|
* @param {Bytes<32>} spender - The approved spender.
|
|
637
|
-
* @return {EscrowEntry} - The encrypted escrow entry (
|
|
662
|
+
* @return {EscrowEntry} - The encrypted escrow entry (a placeholder with the
|
|
663
|
+
* absent-allowance sentinel if none).
|
|
638
664
|
*/
|
|
639
665
|
export circuit allowance(owner: Bytes<32>, spender: Bytes<32>): EscrowEntry {
|
|
666
|
+
assertInitialized();
|
|
640
667
|
if (!_escrow.member(disclose(owner)) ||
|
|
641
668
|
!_escrow.lookup(disclose(owner)).member(disclose(spender))) {
|
|
642
669
|
const id = constructJubjubPoint(0 as Field, 1 as Field);
|
|
@@ -656,12 +683,17 @@ module ConfidentialFungibleToken {
|
|
|
656
683
|
/**
|
|
657
684
|
* @description Returns whether `account` has registered an encryption key.
|
|
658
685
|
*
|
|
659
|
-
* @constraints k=9, rows=
|
|
686
|
+
* @constraints k=9, rows=305
|
|
687
|
+
*
|
|
688
|
+
* Requirements:
|
|
689
|
+
*
|
|
690
|
+
* - Contract is initialized.
|
|
660
691
|
*
|
|
661
692
|
* @param {Bytes<32>} account - The account to query.
|
|
662
693
|
* @return {Boolean} - True if `account` is registered.
|
|
663
694
|
*/
|
|
664
695
|
export circuit isRegistered(account: Bytes<32>): Boolean {
|
|
696
|
+
assertInitialized();
|
|
665
697
|
return _encryptionKeys.member(disclose(account));
|
|
666
698
|
}
|
|
667
699
|
|
|
@@ -812,6 +844,12 @@ module ConfidentialFungibleToken {
|
|
|
812
844
|
* `sum(balances) == totalSupply` invariant. Pair it with a debit (as `transfer`
|
|
813
845
|
* does) or a supply increase (as a supply layer's `mint` does).
|
|
814
846
|
*
|
|
847
|
+
* Requirements:
|
|
848
|
+
*
|
|
849
|
+
* - Contract is initialized.
|
|
850
|
+
* - `value` is within `MAX_TRANSFER_VALUE()`.
|
|
851
|
+
* - `account` is non-zero and registered.
|
|
852
|
+
*
|
|
815
853
|
* @param account - The recipient account id.
|
|
816
854
|
* @param value - The amount to credit.
|
|
817
855
|
*/
|
|
@@ -928,7 +966,7 @@ module ConfidentialFungibleToken {
|
|
|
928
966
|
* credits `to`, and pushes an encrypted memo to `to`. The amount is hidden;
|
|
929
967
|
* the (sender, recipient) pair is public.
|
|
930
968
|
*
|
|
931
|
-
* @constraints k=16, rows=
|
|
969
|
+
* @constraints k=16, rows=41621
|
|
932
970
|
*
|
|
933
971
|
* @notice Returns the caller's (sender's) `accountId` for caller-side gating.
|
|
934
972
|
* The sender is derived from the same authentication `_debit` performs, so the
|
|
@@ -946,7 +984,6 @@ module ConfidentialFungibleToken {
|
|
|
946
984
|
* @return {Bytes<32>} - The caller's (sender's) accountId.
|
|
947
985
|
*/
|
|
948
986
|
export circuit transfer(to: Bytes<32>, value: Uint<128>): Bytes<32> {
|
|
949
|
-
assertInitialized();
|
|
950
987
|
// Derive the sender from the same authentication `_debit` uses, so the
|
|
951
988
|
// returned id is exactly the account whose funds moved.
|
|
952
989
|
const senderId = _debit(value);
|
|
@@ -966,7 +1003,7 @@ module ConfidentialFungibleToken {
|
|
|
966
1003
|
* operations (`mint`/`burn`) live in a separate layer outside this conserving
|
|
967
1004
|
* surface, and only they may break conservation.
|
|
968
1005
|
*
|
|
969
|
-
* @constraints k=16, rows=
|
|
1006
|
+
* @constraints k=16, rows=41610
|
|
970
1007
|
*
|
|
971
1008
|
* @notice Like `transfer`, the credit lands in the recipient's pending pool
|
|
972
1009
|
* (see the dual-balance note); the caller sweeps their own incoming value.
|
|
@@ -992,7 +1029,6 @@ module ConfidentialFungibleToken {
|
|
|
992
1029
|
* @return {Bytes<32>} - The caller's accountId (for caller-side gating).
|
|
993
1030
|
*/
|
|
994
1031
|
export circuit _move(to: Bytes<32>, value: Uint<128>): Bytes<32> {
|
|
995
|
-
assertInitialized();
|
|
996
1032
|
const senderId = _debit(value);
|
|
997
1033
|
_credit(to, value);
|
|
998
1034
|
return senderId;
|
|
@@ -1125,7 +1161,7 @@ module ConfidentialFungibleToken {
|
|
|
1125
1161
|
* caller via `approve`) and credits it to `to`, reducing both escrow copies by
|
|
1126
1162
|
* `value`. The amount is hidden.
|
|
1127
1163
|
*
|
|
1128
|
-
*
|
|
1164
|
+
* @constraints k=17, rows=68922
|
|
1129
1165
|
*
|
|
1130
1166
|
* @notice Returns the caller's (spender's) `accountId` for caller-side gating.
|
|
1131
1167
|
*
|
|
@@ -1135,6 +1171,7 @@ module ConfidentialFungibleToken {
|
|
|
1135
1171
|
* - `value` is within `MAX_TRANSFER_VALUE()`.
|
|
1136
1172
|
* - `to` is registered and is not the zero account.
|
|
1137
1173
|
* - An escrow from `fromAddress` to the caller exists with at least `value`.
|
|
1174
|
+
* - `fromAddress` and the caller are registered.
|
|
1138
1175
|
*
|
|
1139
1176
|
* @param {Bytes<32>} fromAddress - The owner whose escrow is drawn on.
|
|
1140
1177
|
* @param {Bytes<32>} to - The recipient account.
|
|
@@ -1146,7 +1183,6 @@ module ConfidentialFungibleToken {
|
|
|
1146
1183
|
to: Bytes<32>,
|
|
1147
1184
|
value: Uint<128>
|
|
1148
1185
|
): Bytes<32> {
|
|
1149
|
-
assertInitialized();
|
|
1150
1186
|
_assertValueInBound(value);
|
|
1151
1187
|
assert(to != default<Bytes<32>>,
|
|
1152
1188
|
"ConfidentialFungibleToken: invalid receiver");
|
|
@@ -1299,6 +1335,13 @@ module ConfidentialFungibleToken {
|
|
|
1299
1335
|
* not prove the post-refund balance on a later re-approve/revoke. See the
|
|
1300
1336
|
* `EscrowEntry` field doc.
|
|
1301
1337
|
*
|
|
1338
|
+
* Requirements:
|
|
1339
|
+
*
|
|
1340
|
+
* - Contract is initialized.
|
|
1341
|
+
* - `value` is within `MAX_TRANSFER_VALUE()`.
|
|
1342
|
+
* - An escrow from `fromAddress` to the caller exists with at least `value`.
|
|
1343
|
+
* - `fromAddress` and the caller are registered.
|
|
1344
|
+
*
|
|
1302
1345
|
* @param fromAddress - The owner whose escrow the caller (spender) draws on.
|
|
1303
1346
|
* @param value - The amount to consume from the allowance.
|
|
1304
1347
|
*/
|
|
@@ -1310,6 +1353,10 @@ module ConfidentialFungibleToken {
|
|
|
1310
1353
|
assert(_escrow.member(disclose(fromAddress)) &&
|
|
1311
1354
|
_escrow.lookup(disclose(fromAddress)).member(disclose(spenderId)),
|
|
1312
1355
|
"ConfidentialFungibleToken: no escrow");
|
|
1356
|
+
assert(_encryptionKeys.member(disclose(spenderId)),
|
|
1357
|
+
"ConfidentialFungibleToken: spender not registered");
|
|
1358
|
+
assert(_encryptionKeys.member(disclose(fromAddress)),
|
|
1359
|
+
"ConfidentialFungibleToken: owner not registered");
|
|
1313
1360
|
|
|
1314
1361
|
const entry = _escrow.lookup(disclose(fromAddress)).lookup(disclose(spenderId));
|
|
1315
1362
|
|
|
@@ -1374,13 +1421,14 @@ module ConfidentialFungibleToken {
|
|
|
1374
1421
|
* recipient credit. The building block for a composing contract's
|
|
1375
1422
|
* `burnFrom`; it performs no supply accounting (see `_burn`).
|
|
1376
1423
|
*
|
|
1377
|
-
*
|
|
1424
|
+
* @constraints k=16, rows=42205
|
|
1378
1425
|
*
|
|
1379
1426
|
* Requirements:
|
|
1380
1427
|
*
|
|
1381
1428
|
* - Contract is initialized.
|
|
1382
1429
|
* - `value` is within `MAX_TRANSFER_VALUE()`.
|
|
1383
1430
|
* - An escrow from `fromAddress` to the caller exists with at least `value`.
|
|
1431
|
+
* - `fromAddress` and the caller are registered.
|
|
1384
1432
|
*
|
|
1385
1433
|
* @param {Bytes<32>} fromAddress - The owner whose escrow is consumed.
|
|
1386
1434
|
* @param {Uint<128>} value - The amount to burn.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0 (token/FungibleToken.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -130,8 +130,6 @@ module FungibleToken {
|
|
|
130
130
|
* @dev This MUST be called in the implementing contract's constructor. Failure to do so
|
|
131
131
|
* can lead to an irreparable contract.
|
|
132
132
|
*
|
|
133
|
-
* @constraints k=10, rows=71
|
|
134
|
-
*
|
|
135
133
|
* @param {Opaque<"string">} name_ - The name of the token.
|
|
136
134
|
* @param {Opaque<"string">} symbol_ - The symbol of the token.
|
|
137
135
|
* @param {Uint<8>} decimals_ - The number of decimals used to get the user representation.
|
package/token/MultiToken.compact
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0 (token/MultiToken.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -176,8 +176,6 @@ module MultiToken {
|
|
|
176
176
|
/**
|
|
177
177
|
* @description Initializes the contract by setting the base URI for all tokens.
|
|
178
178
|
*
|
|
179
|
-
* @constraints k=6, rows=31
|
|
180
|
-
*
|
|
181
179
|
* Requirements:
|
|
182
180
|
*
|
|
183
181
|
* - Must be called in the contract's constructor.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0 (token/NativeShieldedToken.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -230,7 +230,13 @@ module NativeShieldedToken {
|
|
|
230
230
|
*
|
|
231
231
|
* @notice The consumer SHOULD persist the returned coin info in its own
|
|
232
232
|
* ledger state: it is the contract's holding and is not otherwise
|
|
233
|
-
* recoverable.
|
|
233
|
+
* recoverable. The coin is already claimed as a receive by the mint, so a
|
|
234
|
+
* custody module must record it without calling `receiveShielded` on it
|
|
235
|
+
* again (see the recipient-arm note in `NativeShieldedTokenCore`).
|
|
236
|
+
* `ShieldedTreasury._deposit` claims on the way in and is not that path;
|
|
237
|
+
* a record-only circuit is tracked in compact-contracts#1112. Until a
|
|
238
|
+
* custody module is composed, the only spend of a contract-held coin is
|
|
239
|
+
* `_burnFromSelf`.
|
|
234
240
|
*
|
|
235
241
|
* @constraints k=14, rows=10221
|
|
236
242
|
*
|
|
@@ -310,7 +316,9 @@ module NativeShieldedToken {
|
|
|
310
316
|
*
|
|
311
317
|
* @dev The consumer SHOULD persist the returned change coin info in its own
|
|
312
318
|
* ledger state: the change replaces `coin` as the contract's holding, and
|
|
313
|
-
* its info is not otherwise recoverable.
|
|
319
|
+
* its info is not otherwise recoverable. Like a `_mintToSelf` coin, the
|
|
320
|
+
* change is already claimed as a receive, so a custody module must record
|
|
321
|
+
* it without a second `receiveShielded`.
|
|
314
322
|
*
|
|
315
323
|
* @constraints k=15, rows=23208
|
|
316
324
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0 (token/NonFungibleToken.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -165,8 +165,6 @@ module NonFungibleToken {
|
|
|
165
165
|
* This MUST be called in the implementing contract's constructor.
|
|
166
166
|
* Failure to do so can lead to an irreparable contract.
|
|
167
167
|
*
|
|
168
|
-
* @constraints k=6, rows=52
|
|
169
|
-
*
|
|
170
168
|
* Requirements:
|
|
171
169
|
*
|
|
172
170
|
* - Contract is not initialized.
|