@openzeppelin/compact-contracts 0.3.0-alpha.1 → 0.3.0-rc.1

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 (39) hide show
  1. package/access/AccessControl.compact +1 -1
  2. package/access/Ownable.compact +1 -1
  3. package/access/ShieldedAccessControl.compact +1 -1
  4. package/access/ZOwnablePK.compact +1 -1
  5. package/crypto/EcdhMask.compact +1 -1
  6. package/crypto/ElGamal.compact +44 -3
  7. package/multisig/ForwarderPrivate.compact +2 -2
  8. package/multisig/ForwarderShielded.compact +2 -2
  9. package/multisig/ForwarderUnshielded.compact +2 -2
  10. package/multisig/ProposalManager.compact +35 -1
  11. package/multisig/ShieldedTreasury.compact +34 -4
  12. package/multisig/ShieldedTreasuryStateless.compact +46 -17
  13. package/multisig/Signer.compact +45 -41
  14. package/multisig/UnshieldedTreasury.compact +44 -17
  15. package/multisig/presets/ShieldedMultiSig.compact +4 -4
  16. package/multisig/presets/ShieldedMultiSigV2.compact +2 -2
  17. package/multisig/presets/ShieldedMultiSigV3.compact +2 -2
  18. package/multisig/presets/forwarder/ForwarderPrivate.compact +1 -1
  19. package/multisig/presets/forwarder/ForwarderShielded.compact +1 -1
  20. package/multisig/presets/forwarder/ForwarderUnshielded.compact +1 -1
  21. package/package.json +3 -3
  22. package/security/Allowlist.compact +1 -1
  23. package/security/Blocklist.compact +1 -1
  24. package/security/Initializable.compact +1 -1
  25. package/security/Pausable.compact +1 -1
  26. package/token/ConfidentialFungibleToken.compact +289 -75
  27. package/token/FungibleToken.compact +1 -1
  28. package/token/MultiToken.compact +1 -1
  29. package/token/NativeShieldedToken.compact +60 -11
  30. package/token/NativeShieldedTokenCore.compact +41 -9
  31. package/token/NativeShieldedTokenFamily.compact +61 -11
  32. package/token/NonFungibleToken.compact +63 -19
  33. package/token/extensions/ConfidentialFungibleTokenPublicSupply.compact +1 -1
  34. package/token/extensions/NativeShieldedTokenDerivedNonce.compact +1 -1
  35. package/token/extensions/{NativeShieldedTokenFamilySupply.compact → NativeShieldedTokenFamilyPublicSupply.compact} +11 -11
  36. package/token/extensions/{NativeShieldedTokenSupply.compact → NativeShieldedTokenPublicSupply.compact} +11 -11
  37. package/token/extensions/{NativeShieldedTokenSupplyCore.compact → NativeShieldedTokenPublicSupplyCore.compact} +9 -9
  38. package/utils/Utils.compact +11 -1
  39. package/multisig/SignerManager.compact +0 -205
@@ -1,16 +1,16 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.2.0 (token/extensions/NativeShieldedTokenFamilySupply.compact)
2
+ // OpenZeppelin Compact Contracts v0.2.0 (token/extensions/NativeShieldedTokenFamilyPublicSupply.compact)
3
3
 
4
4
  pragma language_version >= 0.23.0;
5
5
 
6
6
  /**
7
- * @module NativeShieldedTokenFamilySupply
7
+ * @module NativeShieldedTokenFamilyPublicSupply
8
8
  * @description Optional standalone extension that adds per-domain on-chain
9
9
  * supply accounting to a `NativeShieldedTokenFamily`. It exposes `_addMinted` /
10
10
  * `_addBurned` building blocks plus the `totalMinted` / `totalBurned` /
11
11
  * `totalSupply` getters, each keyed by domain. It imports no token module.
12
12
  *
13
- * It is a thin wrapper over `NativeShieldedTokenSupplyCore`, forwarding the
13
+ * It is a thin wrapper over `NativeShieldedTokenPublicSupplyCore`, forwarding the
14
14
  * caller's per-call `domain`, so the accounting logic and guarantees live in
15
15
  * the shared core.
16
16
  *
@@ -20,7 +20,7 @@ pragma language_version >= 0.23.0;
20
20
  *
21
21
  * export circuit mint(
22
22
  * domain: Bytes<32>,
23
- * recipient: Either<ZswapCoinPublicKey, ContractAddress>,
23
+ * recipient: ZswapCoinPublicKey,
24
24
  * amount: Uint<64>,
25
25
  * nonce: Bytes<32>
26
26
  * ): ShieldedCoinInfo {
@@ -33,7 +33,7 @@ pragma language_version >= 0.23.0;
33
33
  * domain: Bytes<32>,
34
34
  * coin: ShieldedCoinInfo,
35
35
  * amount: Uint<128>,
36
- * refundTo: Either<ZswapCoinPublicKey, ContractAddress>
36
+ * refundTo: ZswapCoinPublicKey
37
37
  * ): Maybe<ShieldedCoinInfo> {
38
38
  * const refund = Family__burn(domain, coin, amount, refundTo);
39
39
  * Supply__addBurned(domain, amount);
@@ -51,25 +51,25 @@ pragma language_version >= 0.23.0;
51
51
  *
52
52
  * @dev Mint amounts are already public via the protocol's `shieldedMints`
53
53
  * effect, so `_addMinted` adds accounting, not disclosure. See
54
- * `NativeShieldedTokenSupplyCore` for the exact / lower-bound / upper-bound
54
+ * `NativeShieldedTokenPublicSupplyCore` for the exact / lower-bound / upper-bound
55
55
  * guarantees, the per-domain `burned <= minted` invariant, and the mint-side
56
56
  * drift caveat.
57
57
  *
58
58
  * @warning Pair every mint with `_addMinted` and every burn with `_addBurned` on
59
59
  * every path, under the matching domain; mis-wiring is a security-critical,
60
60
  * undetectable error (e.g. an undercounted mint makes `_addBurned` reject
61
- * legitimate burns). See `NativeShieldedTokenSupplyCore`.
61
+ * legitimate burns). See `NativeShieldedTokenPublicSupplyCore`.
62
62
  */
63
- module NativeShieldedTokenFamilySupply {
63
+ module NativeShieldedTokenFamilyPublicSupply {
64
64
  import CompactStandardLibrary;
65
- import "./NativeShieldedTokenSupplyCore" prefix Core_;
65
+ import "./NativeShieldedTokenPublicSupplyCore" prefix Core_;
66
66
 
67
67
  // Circuits use the `Core_` prefix above. The named import/re-export below is
68
68
  // only for the core supply ledger keys, so the implementing contract's ledger
69
69
  // keys read as `_totalMinted` / `_totalBurned` rather than
70
- // `NativeShieldedTokenSupplyCore__totalMinted`. The circuit names are
70
+ // `NativeShieldedTokenPublicSupplyCore__totalMinted`. The circuit names are
71
71
  // intentionally NOT imported unprefixed, to avoid potential clashes.
72
- import { _totalMinted, _totalBurned } from "./NativeShieldedTokenSupplyCore";
72
+ import { _totalMinted, _totalBurned } from "./NativeShieldedTokenPublicSupplyCore";
73
73
  export { _totalMinted, _totalBurned };
74
74
 
75
75
  /**
@@ -1,16 +1,16 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.2.0 (token/extensions/NativeShieldedTokenSupply.compact)
2
+ // OpenZeppelin Compact Contracts v0.2.0 (token/extensions/NativeShieldedTokenPublicSupply.compact)
3
3
 
4
4
  pragma language_version >= 0.23.0;
5
5
 
6
6
  /**
7
- * @module NativeShieldedTokenSupply
7
+ * @module NativeShieldedTokenPublicSupply
8
8
  * @description Optional standalone extension that adds on-chain supply
9
9
  * accounting to a `NativeShieldedToken`. It exposes scalar `_addMinted` /
10
10
  * `_addBurned` building blocks plus the `totalMinted` / `totalBurned` /
11
11
  * `totalSupply` getters. It imports no token module.
12
12
  *
13
- * It is a thin wrapper over `NativeShieldedTokenSupplyCore`, forwarding a
13
+ * It is a thin wrapper over `NativeShieldedTokenPublicSupplyCore`, forwarding a
14
14
  * single fixed key (the paired contract has exactly one token type), so the
15
15
  * accounting logic and guarantees live in the shared core.
16
16
  *
@@ -18,7 +18,7 @@ pragma language_version >= 0.23.0;
18
18
  * pieces, calling the accounting block alongside the matching token op:
19
19
  *
20
20
  * export circuit mint(
21
- * recipient: Either<ZswapCoinPublicKey, ContractAddress>,
21
+ * recipient: ZswapCoinPublicKey,
22
22
  * amount: Uint<64>,
23
23
  * nonce: Bytes<32>
24
24
  * ): ShieldedCoinInfo {
@@ -30,7 +30,7 @@ pragma language_version >= 0.23.0;
30
30
  * export circuit burn(
31
31
  * coin: ShieldedCoinInfo,
32
32
  * amount: Uint<128>,
33
- * refundTo: Either<ZswapCoinPublicKey, ContractAddress>
33
+ * refundTo: ZswapCoinPublicKey
34
34
  * ): Maybe<ShieldedCoinInfo> {
35
35
  * const refund = Token__burn(coin, amount, refundTo);
36
36
  * Supply__addBurned(amount);
@@ -48,24 +48,24 @@ pragma language_version >= 0.23.0;
48
48
  *
49
49
  * @dev Mint amounts are already public via the protocol's `shieldedMints`
50
50
  * effect, so `_addMinted` adds accounting, not disclosure. See
51
- * `NativeShieldedTokenSupplyCore` for the exact / lower-bound / upper-bound
51
+ * `NativeShieldedTokenPublicSupplyCore` for the exact / lower-bound / upper-bound
52
52
  * guarantees, the `burned <= minted` invariant, and the mint-side drift caveat.
53
53
  *
54
54
  * @warning Pair every mint with `_addMinted` and every burn with `_addBurned` on
55
55
  * every path; mis-wiring is a security-critical, undetectable error (e.g. an
56
56
  * undercounted mint makes `_addBurned` reject legitimate burns). See
57
- * `NativeShieldedTokenSupplyCore`.
57
+ * `NativeShieldedTokenPublicSupplyCore`.
58
58
  */
59
- module NativeShieldedTokenSupply {
59
+ module NativeShieldedTokenPublicSupply {
60
60
  import CompactStandardLibrary;
61
- import "./NativeShieldedTokenSupplyCore" prefix Core_;
61
+ import "./NativeShieldedTokenPublicSupplyCore" prefix Core_;
62
62
 
63
63
  // Circuits use the `Core_` prefix above. The named import/re-export below is
64
64
  // only for the core supply ledger keys, so the implementing contract's ledger
65
65
  // keys read as `_totalMinted` / `_totalBurned` rather than
66
- // `NativeShieldedTokenSupplyCore__totalMinted`. The circuit names are
66
+ // `NativeShieldedTokenPublicSupplyCore__totalMinted`. The circuit names are
67
67
  // intentionally NOT imported unprefixed, to avoid potential clashes.
68
- import { _totalMinted, _totalBurned } from "./NativeShieldedTokenSupplyCore";
68
+ import { _totalMinted, _totalBurned } from "./NativeShieldedTokenPublicSupplyCore";
69
69
  export { _totalMinted, _totalBurned };
70
70
 
71
71
  /**
@@ -1,10 +1,10 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.2.0 (token/extensions/NativeShieldedTokenSupplyCore.compact)
2
+ // OpenZeppelin Compact Contracts v0.2.0 (token/extensions/NativeShieldedTokenPublicSupplyCore.compact)
3
3
 
4
4
  pragma language_version >= 0.23.0;
5
5
 
6
6
  /**
7
- * @module NativeShieldedTokenSupplyCore
7
+ * @module NativeShieldedTokenPublicSupplyCore
8
8
  * @description Shared, domain-keyed core of the optional supply-accounting
9
9
  * extension. It owns the per-domain minted/burned maps and exposes the
10
10
  * `_addMinted` / `_addBurned` building blocks plus the `totalMinted` /
@@ -13,12 +13,12 @@ pragma language_version >= 0.23.0;
13
13
  * This module is NOT meant to be composed directly. It is the de-duplicated
14
14
  * base behind the two user-facing flavors:
15
15
  *
16
- * - `NativeShieldedTokenSupply` — pairs with `NativeShieldedToken`; forwards a
16
+ * - `NativeShieldedTokenPublicSupply` — pairs with `NativeShieldedToken`; forwards a
17
17
  * single fixed key (the contract has one token type).
18
- * - `NativeShieldedTokenFamilySupply` — pairs with `NativeShieldedTokenFamily`;
18
+ * - `NativeShieldedTokenFamilyPublicSupply` — pairs with `NativeShieldedTokenFamily`;
19
19
  * forwards the caller's per-call `domain`.
20
20
  *
21
- * @dev Assertion messages use the generic `NativeShieldedTokenSupply:` prefix
21
+ * @dev Assertion messages use the generic `NativeShieldedTokenPublicSupply:` prefix
22
22
  * so they read sensibly from either flavor. There is no initialization: an
23
23
  * absent domain key reads as 0, and the getters do not gate on the paired token
24
24
  * module's init flag (a counter reading 0 before init is correct), so init
@@ -51,7 +51,7 @@ pragma language_version >= 0.23.0;
51
51
  * overstates circulating supply.
52
52
  * Call the matching accounting block on every mint and burn path, same domain.
53
53
  */
54
- module NativeShieldedTokenSupplyCore {
54
+ module NativeShieldedTokenPublicSupplyCore {
55
55
  import CompactStandardLibrary;
56
56
  import "../../utils/Utils" prefix Utils_;
57
57
 
@@ -79,7 +79,7 @@ module NativeShieldedTokenSupplyCore {
79
79
  */
80
80
  export circuit _addMinted(domain: Bytes<32>, amount: Uint<64>): [] {
81
81
  const current = totalMinted(domain);
82
- assert(Utils_UINT128_MAX() - current >= amount, "NativeShieldedTokenSupply: arithmetic overflow");
82
+ assert(Utils_UINT128_MAX() - current >= amount, "NativeShieldedTokenPublicSupply: arithmetic overflow");
83
83
  _totalMinted.insert(disclose(domain), disclose((current + amount) as Uint<128>));
84
84
  }
85
85
 
@@ -103,8 +103,8 @@ module NativeShieldedTokenSupplyCore {
103
103
  // First guards the subtraction below from underflowing on an already-corrupt
104
104
  // state (stored burned past minted); the second is the reachable per-call
105
105
  // check that this burn does not push the domain past its minted total.
106
- assert(minted >= current, "NativeShieldedTokenSupply: burned total exceeds minted");
107
- assert(minted - current >= amount, "NativeShieldedTokenSupply: burn exceeds available supply");
106
+ assert(minted >= current, "NativeShieldedTokenPublicSupply: burned total exceeds minted");
107
+ assert(minted - current >= amount, "NativeShieldedTokenPublicSupply: burn exceeds available supply");
108
108
  _totalBurned.insert(disclose(domain), disclose((current + amount) as Uint<128>));
109
109
  }
110
110
 
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.3.0-alpha.1 (utils/Utils.compact)
2
+ // OpenZeppelin Compact Contracts v0.3.0-rc.1 (utils/Utils.compact)
3
3
 
4
4
  pragma language_version >= 0.23.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.
@@ -1,205 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.3.0-alpha.1 (multisig/SignerManager.compact)
3
-
4
- pragma language_version >= 0.23.0;
5
-
6
- /**
7
- * @module SignerManager<T>
8
- * @description Manages signer registry, threshold enforcement, and signer
9
- * validation for multisig governance contracts.
10
- *
11
- * Parameterized over the signer identity type `T`, allowing the consuming
12
- * contract to choose the identity mechanism at import time. Common
13
- * instantiations include:
14
- *
15
- * - `Either<ZswapCoinPublicKey, ContractAddress>` for ownPublicKey()-based identity
16
- * - `Bytes<32>` for commitment-based identity (e.g., hash of ECDSA public key)
17
- * - `NativePoint` for Schnorr/MuSig aggregated key
18
- *
19
- * SignerManager does not resolve caller identity. It receives a validated
20
- * caller from the contract layer and checks it against the registry.
21
- * This separation allows the identity mechanism to change without
22
- * modifying the module.
23
- *
24
- * Underscore-prefixed circuits (_addSigner, _removeSigner,
25
- * _changeThreshold) have no access control enforcement. The consuming
26
- * contract must gate these behind its own authorization policy.
27
- */
28
- module SignerManager<T> {
29
- import CompactStandardLibrary;
30
-
31
- // ─── State ──────────────────────────────────────────────────────────────────
32
-
33
- export ledger _signers: Set<T>;
34
- export ledger _signerCount: Uint<8>;
35
- export ledger _threshold: Uint<8>;
36
-
37
- // ─── Initialization ─────────────────────────────────────────────────────────
38
-
39
- /**
40
- * @description Initializes the signer manager with the given threshold
41
- * and an initial set of signers.
42
- * Must be called in the contract's constructor.
43
- *
44
- * Requirements:
45
- *
46
- * - `thresh` must be greater than 0.
47
- * - `signers` must not contain duplicates.
48
- *
49
- * @param {Vector<n, T>} signers - The initial signer set.
50
- * @param {Uint<8>} thresh - The minimum number of approvals required.
51
- *
52
- * @returns {[]} Empty tuple.
53
- */
54
- export circuit initialize<#n>(
55
- signers: Vector<n, T>,
56
- thresh: Uint<8>
57
- ): [] {
58
- assert(thresh > 0, "SignerManager: threshold must be > 0");
59
- _threshold = disclose(thresh);
60
-
61
- for (const signer of signers) {
62
- _addSigner(signer);
63
- }
64
-
65
- assert(_signerCount >= thresh, "SignerManager: threshold exceeds signer count");
66
- }
67
-
68
- // ─── Guards ─────────────────────────────────────────────────────────────
69
-
70
- /**
71
- * @description Asserts that the given caller is an active signer.
72
- *
73
- * Requirements:
74
- *
75
- * - `caller` must be a member of the signers registry.
76
- *
77
- * @param {T} caller - The identity to validate.
78
- *
79
- * @returns {[]} Empty tuple.
80
- */
81
- export circuit assertSigner(caller: T): [] {
82
- assert(isSigner(caller), "SignerManager: not a signer");
83
- }
84
-
85
- /**
86
- * @description Asserts that the given approval count meets the threshold.
87
- *
88
- * Requirements:
89
- *
90
- * - `approvalCount` must be >= threshold.
91
- *
92
- * @param {Uint<8>} approvalCount - The current number of approvals.
93
- *
94
- * @returns {[]} Empty tuple.
95
- */
96
- export circuit assertThresholdMet(approvalCount: Uint<8>): [] {
97
- assert(approvalCount >= _threshold, "SignerManager: threshold not met");
98
- }
99
-
100
- // ─── View ──────────────────────────────────────────────────────────
101
-
102
- /**
103
- * @description Returns the current signer count.
104
- *
105
- * @returns {Uint<8>} The number of active signers.
106
- */
107
- export circuit getSignerCount(): Uint<8> {
108
- return _signerCount;
109
- }
110
-
111
- /**
112
- * @description Returns the approval threshold.
113
- *
114
- * @returns {Uint<8>} The threshold.
115
- */
116
- export circuit getThreshold(): Uint<8> {
117
- return _threshold;
118
- }
119
-
120
- /**
121
- * @description Returns whether the given account is an active signer.
122
- *
123
- * @param {T} account - The account to check.
124
- *
125
- * @returns {Boolean} True if the account is an active signer.
126
- */
127
- export circuit isSigner(account: T): Boolean {
128
- return _signers.member(disclose(account));
129
- }
130
-
131
- // ─── Signer Management ─────────────────────────────────────────────────────
132
-
133
- /**
134
- * @description Adds a new signer to the registry.
135
- *
136
- * @notice Access control is NOT enforced here.
137
- * The consuming contract must gate this behind its own
138
- * authorization policy.
139
- *
140
- * Requirements:
141
- *
142
- * - `signer` must not already be an active signer.
143
- *
144
- * @param {T} signer - The signer to add.
145
- *
146
- * @returns {[]} Empty tuple.
147
- */
148
- export circuit _addSigner(signer: T): [] {
149
- assert(
150
- !isSigner(signer),
151
- "SignerManager: signer already active"
152
- );
153
-
154
- _signers.insert(disclose(signer));
155
- _signerCount = _signerCount + 1 as Uint<8>;
156
- }
157
-
158
- /**
159
- * @description Removes a signer from the registry.
160
- *
161
- * @notice Access control is NOT enforced here.
162
- * The consuming contract must gate this behind its own
163
- * authorization policy.
164
- *
165
- * Requirements:
166
- *
167
- * - `signer` must be an active signer.
168
- * - Removal must not drop signer count below threshold.
169
- *
170
- * @param {T} signer - The signer to remove.
171
- *
172
- * @returns {[]} Empty tuple.
173
- */
174
- export circuit _removeSigner(signer: T): [] {
175
- assert(isSigner(signer), "SignerManager: not a signer");
176
-
177
- const newCount = _signerCount - 1 as Uint<8>;
178
- assert(newCount >= _threshold, "SignerManager: removal would breach threshold");
179
-
180
- _signers.remove(disclose(signer));
181
- _signerCount = newCount;
182
- }
183
-
184
- /**
185
- * @description Updates the approval threshold.
186
- *
187
- * @notice Access control is NOT enforced here.
188
- * The consuming contract must gate this behind its own
189
- * authorization policy.
190
- *
191
- * Requirements:
192
- *
193
- * - `newThreshold` must be greater than 0.
194
- * - `newThreshold` must not exceed the current signer count.
195
- *
196
- * @param {Uint<8>} newThreshold - The new minimum number of approvals required.
197
- *
198
- * @returns {[]} Empty tuple.
199
- */
200
- export circuit _changeThreshold(newThreshold: Uint<8>): [] {
201
- assert(newThreshold > 0, "SignerManager: threshold must be > 0");
202
- assert(newThreshold <= _signerCount, "SignerManager: threshold exceeds signer count");
203
- _threshold = disclose(newThreshold);
204
- }
205
- }