@openzeppelin/compact-contracts 0.4.0-alpha.1 → 0.4.0-alpha.2

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.
Files changed (46) hide show
  1. package/README.md +9 -5
  2. package/access/AccessControl.compact +13 -13
  3. package/access/Ownable.compact +15 -9
  4. package/access/ShieldedAccessControl.compact +25 -1
  5. package/access/ZOwnablePK.compact +8 -8
  6. package/crypto/EcdhMask.compact +1 -1
  7. package/crypto/Ecdsa.compact +4 -4
  8. package/crypto/Eip712.compact +168 -0
  9. package/crypto/ElGamal.compact +1 -1
  10. package/multisig/EcdsaSignerManager.compact +32 -15
  11. package/multisig/ForwarderPrivate.compact +11 -5
  12. package/multisig/ForwarderShielded.compact +2 -2
  13. package/multisig/ForwarderUnshielded.compact +2 -2
  14. package/multisig/ProposalManager.compact +194 -22
  15. package/multisig/ShieldedTreasury.compact +28 -1
  16. package/multisig/ShieldedTreasuryStateless.compact +1 -1
  17. package/multisig/Signer.compact +27 -79
  18. package/multisig/UnshieldedTreasury.compact +9 -1
  19. package/multisig/{presets/forwarder/ForwarderPrivate.compact → examples/ForwarderPrivateExample.compact} +3 -3
  20. package/multisig/{presets/forwarder/ForwarderShielded.compact → examples/ForwarderShieldedExample.compact} +3 -3
  21. package/multisig/{presets/forwarder/ForwarderUnshielded.compact → examples/ForwarderUnshieldedExample.compact} +3 -3
  22. package/multisig/examples/NativeShieldedTokenIssuerExample.compact +143 -0
  23. package/multisig/examples/ShieldedMultiSigV2Example.compact +77 -0
  24. package/multisig/presets/NativeShieldedTokenIssuer.compact +542 -0
  25. package/multisig/presets/ShieldedMultiSigV2.compact +251 -188
  26. package/package.json +15 -11
  27. package/security/Allowlist.compact +5 -5
  28. package/security/Blocklist.compact +5 -5
  29. package/security/Initializable.compact +8 -4
  30. package/security/Pausable.compact +10 -6
  31. package/token/ConfidentialFungibleToken.compact +80 -21
  32. package/token/FungibleToken.compact +35 -21
  33. package/token/MultiToken.compact +15 -15
  34. package/token/NativeShieldedToken.compact +9 -9
  35. package/token/NativeShieldedTokenCore.compact +19 -9
  36. package/token/NativeShieldedTokenFamily.compact +9 -9
  37. package/token/NonFungibleToken.compact +32 -27
  38. package/token/extensions/ConfidentialFungibleTokenPublicSupply.compact +11 -6
  39. package/token/extensions/NativeShieldedTokenDerivedNonce.compact +2 -2
  40. package/token/extensions/NativeShieldedTokenFamilyPublicSupply.compact +5 -5
  41. package/token/extensions/NativeShieldedTokenPublicSupply.compact +5 -5
  42. package/token/extensions/NativeShieldedTokenPublicSupplyCore.compact +5 -5
  43. package/utils/EvmAbi.compact +134 -0
  44. package/utils/Utils.compact +1 -1
  45. package/multisig/presets/ShieldedMultiSig.compact +0 -227
  46. package/multisig/presets/ShieldedMultiSigV3.compact +0 -311
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.1 (multisig/Signer.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.2 (multisig/Signer.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -37,78 +37,41 @@ pragma language_version >= 0.26.0;
37
37
  * _changeThreshold) have no access control enforcement. The consuming
38
38
  * contract must gate these behind its own authorization policy.
39
39
  *
40
- * Contracts may handle their own initialization and this module
41
- * supports custom flows. Thus, contracts may choose to not
42
- * call `initialize` in the contract's constructor. Contracts MUST NOT
43
- * call `initialize` outside of the constructor context because
44
- * this could corrupt the signer set and threshold configuration.
40
+ * The module has no `initialize`. The consuming contract, or a manager module
41
+ * wrapping this one, registers signers with `_addSigner` and sets the
42
+ * threshold with `_changeThreshold` / `_setThreshold`, either from the
43
+ * constructor or behind its own authorization policy. Leaving them ungated
44
+ * lets the first caller register their own signer set and take control of
45
+ * the contract.
45
46
  *
46
- * `_isInitialized` records only whether `initialize` has run; it gates
47
- * re-entry into `initialize` and nothing else. No other circuit consults it,
48
- * so a contract that configures signers through its own flow
49
- * (`_addSigner` / `_setThreshold`) is fully functional without ever calling
50
- * `initialize`. Provided it gates those circuits behind its own
51
- * authorization policy. Leaving them ungated lets the first caller register
52
- * their own signer set and take control of the contract.
53
- *
54
- * @notice Not asserting initialization on the guard and view circuits is a
55
- * deliberate divergence from the other modules in this library, which do.
56
- * Those modules gate a zero-valued identity (an owner, a role holder); this
57
- * one gates an empty collection, which rejects by absence. Safety here comes
58
- * from the state rather than from a flag: an empty registry makes `isSigner`
47
+ * @notice The guard and view circuits carry no "configured" flag, a
48
+ * deliberate divergence from the other modules in this library. Those gate a
49
+ * zero-valued identity (an owner, a role holder); this one gates an empty
50
+ * collection, which rejects by absence. An empty registry makes `isSigner`
59
51
  * false for every input, so `assertSigner` rejects every caller, and a zero
60
52
  * `_threshold` makes `assertThresholdMet` reject before it compares any
61
- * approval count regardless of how the threshold came to be zero. Contracts
62
- * needing a "configured" signal beyond that should track one at the contract
63
- * layer.
53
+ * approval count. Contracts needing a "configured" signal beyond that should
54
+ * track one at the contract layer.
64
55
  */
65
56
  module Signer<T> {
66
57
  import CompactStandardLibrary;
67
58
 
68
59
  // ─── State ──────────────────────────────────────────────────────────────────
69
60
 
61
+ /**
62
+ * @description The registered signer set. `T` is chosen by the consuming
63
+ * contract, so a signer is whatever identity that contract authenticates.
64
+ */
70
65
  export ledger _signers: Set<T>;
71
- export ledger _signerCount: Uint<8>;
72
- export ledger _threshold: Uint<8>;
73
-
74
66
  /**
75
- * @description Initialization flag, tracked per-module to avoid the compiler's
76
- * shared transitive-dependency state bug (LFDT-Minokawa/compact#270). See the
77
- * Initializable module for rationale.
67
+ * @description The number of registered signers.
78
68
  */
79
- export ledger _isInitialized: Boolean;
80
-
81
- // ─── Initialization ─────────────────────────────────────────────────────────
82
-
69
+ export ledger _signerCount: Uint<8>;
83
70
  /**
84
- * @description Initializes the signer module with the given threshold
85
- * and an initial set of signers.
86
- * If used, it should only be called in the contract's constructor.
87
- *
88
- * Requirements:
89
- *
90
- * - If used, can only be called once (in the constructor).
91
- * - `thresh` must not be zero.
92
- * - `thresh` must not exceed the number of `signers`.
93
- * - `signers` must not contain duplicates.
94
- *
95
- * @param {Vector<n, T>} signers - The initial signer set.
96
- * @param {Uint<8>} thresh - The minimum number of approvals required.
97
- * @returns {[]} Empty tuple.
71
+ * @description How many approvals an action requires. Never zero once set,
72
+ * and removals that would drop `_signerCount` below it are rejected.
98
73
  */
99
- export circuit initialize<#n>(
100
- signers: Vector<n, T>,
101
- thresh: Uint<8>
102
- ): [] {
103
- assertNotInitialized();
104
- _isInitialized = true;
105
-
106
- for (const signer of signers) {
107
- _addSigner(signer);
108
- }
109
-
110
- _changeThreshold(thresh);
111
- }
74
+ export ledger _threshold: Uint<8>;
112
75
 
113
76
  // ─── Guards ─────────────────────────────────────────────────────────────
114
77
 
@@ -140,7 +103,7 @@ module Signer<T> {
140
103
  * the remaining signers satisfy, and bounding the count would reject those.
141
104
  * See the stale-signer-set guidance in the module header.
142
105
  *
143
- * @circuitInfo k=9, rows=54
106
+ * @constraints k=9, rows=52
144
107
  *
145
108
  * Requirements:
146
109
  *
@@ -162,7 +125,7 @@ module Signer<T> {
162
125
  * @description Returns the current signer count. Returns zero when no
163
126
  * signers have been registered.
164
127
  *
165
- * @circuitInfo k=6, rows=26
128
+ * @constraints k=6, rows=24
166
129
  *
167
130
  * @returns {Uint<8>} The number of active signers.
168
131
  */
@@ -174,7 +137,7 @@ module Signer<T> {
174
137
  * @description Returns the approval threshold. Returns zero when the
175
138
  * threshold has not been set.
176
139
  *
177
- * @circuitInfo k=6, rows=26
140
+ * @constraints k=6, rows=24
178
141
  *
179
142
  * @returns {Uint<8>} The threshold.
180
143
  */
@@ -250,7 +213,7 @@ module Signer<T> {
250
213
  * The consuming contract must gate this behind its own
251
214
  * authorization policy.
252
215
  *
253
- * @circuitInfo k=9, rows=53
216
+ * @constraints k=9, rows=51
254
217
  *
255
218
  * Requirements:
256
219
  *
@@ -285,7 +248,7 @@ module Signer<T> {
285
248
  * authorization policy. Use `_changeThreshold` for
286
249
  * operational threshold changes with signer count validation.
287
250
  *
288
- * @circuitInfo k=6, rows=40
251
+ * @constraints k=6, rows=38
289
252
  *
290
253
  * Requirements:
291
254
  *
@@ -298,19 +261,4 @@ module Signer<T> {
298
261
  assert(newThreshold != 0, "Signer: threshold must not be zero");
299
262
  _threshold = disclose(newThreshold);
300
263
  }
301
-
302
- // ─── Init guards ─────────────────────────────────────────────────────────
303
-
304
- /**
305
- * @description Asserts that the contract has not been initialized, throwing an error if it has.
306
- *
307
- * Requirements:
308
- *
309
- * - Contract must not be initialized.
310
- *
311
- * @return {[]} - Empty tuple.
312
- */
313
- circuit assertNotInitialized(): [] {
314
- assert(!_isInitialized, "Signer: contract already initialized");
315
- }
316
264
  }
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.1 (multisig/UnshieldedTreasury.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.2 (multisig/UnshieldedTreasury.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -37,6 +37,14 @@ module UnshieldedTreasury {
37
37
 
38
38
  // ─── State ──────────────────────────────────────────────────────
39
39
 
40
+ /**
41
+ * @description The treasury's tracked balance per token color. Deposits add
42
+ * to it and sends subtract.
43
+ * @type {Bytes<32>} color - The token color.
44
+ * @type {Uint<128>} balance - The amount currently held of it.
45
+ * @type {Map<color, balance>}
46
+ * @type {Map<Bytes<32>, Uint<128>>} _balances
47
+ */
40
48
  export ledger _balances: Map<Bytes<32>, Uint<128>>;
41
49
 
42
50
  // ─── Deposit ────────────────────────────────────────────────────
@@ -1,10 +1,10 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.1 (multisig/presets/forwarder/ForwarderPrivate.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.2 (multisig/examples/ForwarderPrivateExample.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
6
6
  /**
7
- * @title ForwarderPrivate
7
+ * @title ForwarderPrivateExample
8
8
  * @description Private-parent forwarder. The parent address is hidden
9
9
  * behind a `persistentHash` commitment on the ledger. Coins dwell at
10
10
  * the contract address after deposit; the operator drains them later
@@ -22,7 +22,7 @@ pragma language_version >= 0.26.0;
22
22
  */
23
23
 
24
24
  import CompactStandardLibrary;
25
- import "../../ForwarderPrivate" prefix ForwarderPrivate_;
25
+ import "../ForwarderPrivate" prefix ForwarderPrivate_;
26
26
 
27
27
  export { ShieldedCoinInfo, QualifiedShieldedCoinInfo, ShieldedSendResult, ZswapCoinPublicKey };
28
28
 
@@ -1,10 +1,10 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.1 (multisig/presets/forwarder/ForwarderShielded.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.2 (multisig/examples/ForwarderShieldedExample.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
6
6
  /**
7
- * @title ForwarderShielded
7
+ * @title ForwarderShieldedExample
8
8
  * @description Public-parent forwarder for shielded coins. Receives a
9
9
  * shielded coin and atomically forwards it to the configured parent
10
10
  * recipient, a coin public key.
@@ -22,7 +22,7 @@ pragma language_version >= 0.26.0;
22
22
  */
23
23
 
24
24
  import CompactStandardLibrary;
25
- import "../../ForwarderShielded" prefix Forwarder_;
25
+ import "../ForwarderShielded" prefix Forwarder_;
26
26
 
27
27
  export { ZswapCoinPublicKey, ContractAddress, ShieldedCoinInfo, Either };
28
28
 
@@ -1,10 +1,10 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.1 (multisig/presets/forwarder/ForwarderUnshielded.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.2 (multisig/examples/ForwarderUnshieldedExample.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
6
6
  /**
7
- * @title ForwarderUnshielded
7
+ * @title ForwarderUnshieldedExample
8
8
  * @description Public-parent forwarder for unshielded coins. Receives
9
9
  * an unshielded amount of a given color and atomically forwards it to
10
10
  * the configured parent recipient, a user address.
@@ -24,7 +24,7 @@ pragma language_version >= 0.26.0;
24
24
  */
25
25
 
26
26
  import CompactStandardLibrary;
27
- import "../../ForwarderUnshielded" prefix Forwarder_;
27
+ import "../ForwarderUnshielded" prefix Forwarder_;
28
28
 
29
29
  export { ContractAddress, UserAddress, Either };
30
30
 
@@ -0,0 +1,143 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.2 (multisig/examples/NativeShieldedTokenIssuerExample.compact)
3
+
4
+ pragma language_version >= 0.26.0;
5
+
6
+ /**
7
+ * @title NativeShieldedTokenIssuerExample
8
+ * @description Deployable reference contract for the `NativeShieldedTokenIssuer`
9
+ * preset: a native shielded token whose supply enters only through an
10
+ * ECDSA-authorized mint and leaves only through an ECDSA-authorized burn.
11
+ *
12
+ * The token is non-transferable by construction. There is no transfer circuit,
13
+ * so a holder's only exit is to present the coin back for burn.
14
+ */
15
+
16
+ import CompactStandardLibrary;
17
+
18
+ import "../presets/NativeShieldedTokenIssuer" prefix NativeShieldedTokenIssuer_;
19
+
20
+ export { ZswapCoinPublicKey, ContractAddress, Either, Maybe };
21
+ export { ShieldedCoinInfo, QualifiedShieldedCoinInfo };
22
+
23
+ // Surface the preset's state unprefixed so `ledger()` readers use the keys the
24
+ // modules declare.
25
+ import {
26
+ _counter,
27
+ _domainSeparator,
28
+ _derivedNonceCounter,
29
+ _instanceSalt,
30
+ _signers,
31
+ _signerCount,
32
+ _threshold,
33
+ _domain,
34
+ _name,
35
+ _symbol,
36
+ _decimals,
37
+ _isInitialized,
38
+ } from "../presets/NativeShieldedTokenIssuer";
39
+ export {
40
+ _counter,
41
+ _domainSeparator,
42
+ _derivedNonceCounter,
43
+ _instanceSalt,
44
+ _signers,
45
+ _signerCount,
46
+ _threshold,
47
+ _domain,
48
+ _name,
49
+ _symbol,
50
+ _decimals,
51
+ _isInitialized,
52
+ };
53
+
54
+ /**
55
+ * @description Deploys the issuer with 3 signer commitments, a threshold
56
+ * of 2, and the token's domain and metadata.
57
+ *
58
+ * Requirements:
59
+ *
60
+ * - `signerCommitments` must not contain duplicates.
61
+ * - `instanceSalt` should be cryptographically random.
62
+ *
63
+ * @param {Bytes<32>} instanceSalt - Random salt for signer commitment derivation.
64
+ * @param {Bytes<32>} tokenDomain - Domain separator for this contract's token color.
65
+ * @param {Opaque<"string">} name_ - The token name.
66
+ * @param {Opaque<"string">} symbol_ - The token symbol.
67
+ * @param {Uint<8>} decimals_ - The token decimals.
68
+ * @param {Vector<3, Bytes<32>>} signerCommitments - Hashed signer identities.
69
+ */
70
+ constructor(
71
+ instanceSalt: Bytes<32>,
72
+ tokenDomain: Bytes<32>,
73
+ name_: Opaque<"string">,
74
+ symbol_: Opaque<"string">,
75
+ decimals_: Uint<8>,
76
+ signerCommitments: Vector<3, Bytes<32>>,
77
+ ) {
78
+ NativeShieldedTokenIssuer_initialize(
79
+ instanceSalt,
80
+ tokenDomain,
81
+ name_,
82
+ symbol_,
83
+ decimals_,
84
+ signerCommitments,
85
+ );
86
+ }
87
+
88
+ export pure circuit _calculateSignerId(
89
+ pk: Secp256k1Point,
90
+ salt: Bytes<32>
91
+ ): Bytes<32> {
92
+ return NativeShieldedTokenIssuer__calculateSignerId(pk, salt);
93
+ }
94
+
95
+ export circuit mint(
96
+ amount: Uint<64>,
97
+ recipient: Either<ZswapCoinPublicKey, ContractAddress>,
98
+ pubkeys: Vector<2, Secp256k1Point>,
99
+ signatures: Vector<2, Secp256k1EcdsaSignature>
100
+ ): ShieldedCoinInfo {
101
+ return NativeShieldedTokenIssuer_mint(amount, recipient, pubkeys, signatures);
102
+ }
103
+
104
+ export circuit burn(
105
+ coin: QualifiedShieldedCoinInfo,
106
+ amount: Uint<64>,
107
+ pubkeys: Vector<2, Secp256k1Point>,
108
+ signatures: Vector<2, Secp256k1EcdsaSignature>
109
+ ): Maybe<ShieldedCoinInfo> {
110
+ return NativeShieldedTokenIssuer_burn(coin, amount, pubkeys, signatures);
111
+ }
112
+
113
+ export circuit getNonce(): Uint<64> {
114
+ return NativeShieldedTokenIssuer_getNonce();
115
+ }
116
+
117
+ export circuit name(): Opaque<"string"> {
118
+ return NativeShieldedTokenIssuer_name();
119
+ }
120
+
121
+ export circuit symbol(): Opaque<"string"> {
122
+ return NativeShieldedTokenIssuer_symbol();
123
+ }
124
+
125
+ export circuit decimals(): Uint<8> {
126
+ return NativeShieldedTokenIssuer_decimals();
127
+ }
128
+
129
+ export circuit tokenColor(): Bytes<32> {
130
+ return NativeShieldedTokenIssuer_tokenColor();
131
+ }
132
+
133
+ export circuit getSignerCount(): Uint<8> {
134
+ return NativeShieldedTokenIssuer_getSignerCount();
135
+ }
136
+
137
+ export circuit getThreshold(): Uint<8> {
138
+ return NativeShieldedTokenIssuer_getThreshold();
139
+ }
140
+
141
+ export circuit isSigner(commitment: Bytes<32>): Boolean {
142
+ return NativeShieldedTokenIssuer_isSigner(commitment);
143
+ }
@@ -0,0 +1,77 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.2 (multisig/examples/ShieldedMultiSigV2Example.compact)
3
+
4
+ pragma language_version >= 0.26.0;
5
+
6
+ /**
7
+ * @title ShieldedMultiSigV2Example
8
+ * @description Deployable reference contract for the `ShieldedMultiSigV2`
9
+ * preset: a 2-of-3 wallet whose spends are authorized by ECDSA signatures
10
+ * collected off-chain and verified in a single transaction.
11
+ *
12
+ * Coin data never reaches the public ledger. The operator tracks the wallet's
13
+ * UTXOs off-chain and passes the coin to spend as a circuit argument.
14
+ */
15
+
16
+ import CompactStandardLibrary;
17
+
18
+ import "../presets/ShieldedMultiSigV2" prefix ShieldedMultiSigV2_;
19
+
20
+ export { ShieldedCoinInfo, QualifiedShieldedCoinInfo, ShieldedSendResult };
21
+
22
+ // Surface the preset's domain separator unprefixed so `ledger()` readers see
23
+ // the key name the preset published.
24
+ import { _domainSeparator } from "../presets/ShieldedMultiSigV2";
25
+ export { _domainSeparator };
26
+
27
+ /**
28
+ * @description Deploys the wallet with 3 signer commitments and a threshold.
29
+ *
30
+ * @param {Bytes<32>} instanceSalt - Random salt for commitment derivation.
31
+ * @param {Vector<3, Bytes<32>>} signerCommitments - Hashed signer identities.
32
+ * @param {Uint<8>} thresh - Minimum approvals required.
33
+ */
34
+ constructor(
35
+ instanceSalt: Bytes<32>,
36
+ signerCommitments: Vector<3, Bytes<32>>,
37
+ thresh: Uint<8>,
38
+ ) {
39
+ ShieldedMultiSigV2_initialize(instanceSalt, signerCommitments, thresh);
40
+ }
41
+
42
+ export circuit deposit(coin: ShieldedCoinInfo): [] {
43
+ return ShieldedMultiSigV2_deposit(coin);
44
+ }
45
+
46
+ export circuit execute(
47
+ to: ShieldedMultiSigV2_Proposal_Recipient,
48
+ amount: Uint<128>,
49
+ coin: QualifiedShieldedCoinInfo,
50
+ pubkeys: Vector<2, Secp256k1Point>,
51
+ signatures: Vector<2, Secp256k1EcdsaSignature>
52
+ ): ShieldedSendResult {
53
+ return ShieldedMultiSigV2_execute(to, amount, coin, pubkeys, signatures);
54
+ }
55
+
56
+ export pure circuit _calculateSignerId(
57
+ pk: Secp256k1Point,
58
+ salt: Bytes<32>
59
+ ): Bytes<32> {
60
+ return ShieldedMultiSigV2__calculateSignerId(pk, salt);
61
+ }
62
+
63
+ export circuit getNonce(): Uint<64> {
64
+ return ShieldedMultiSigV2_getNonce();
65
+ }
66
+
67
+ export circuit getSignerCount(): Uint<8> {
68
+ return ShieldedMultiSigV2_getSignerCount();
69
+ }
70
+
71
+ export circuit getThreshold(): Uint<8> {
72
+ return ShieldedMultiSigV2_getThreshold();
73
+ }
74
+
75
+ export circuit isSigner(commitment: Bytes<32>): Boolean {
76
+ return ShieldedMultiSigV2_isSigner(commitment);
77
+ }