@openzeppelin/compact-contracts 0.4.0-alpha.4 → 0.4.0-alpha.5

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 (40) 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/Ecdsa.compact +1 -1
  7. package/crypto/Eip712.compact +1 -1
  8. package/crypto/ElGamal.compact +1 -1
  9. package/multisig/EcdsaSignerManager.compact +9 -7
  10. package/multisig/ForwarderPrivate.compact +1 -1
  11. package/multisig/ForwarderShielded.compact +14 -5
  12. package/multisig/ForwarderUnshielded.compact +1 -1
  13. package/multisig/ProposalManager.compact +1 -1
  14. package/multisig/ShieldedTreasury.compact +1 -1
  15. package/multisig/ShieldedTreasuryStateless.compact +1 -1
  16. package/multisig/Signer.compact +1 -1
  17. package/multisig/UnshieldedTreasury.compact +5 -3
  18. package/multisig/examples/ForwarderPrivateExample.compact +1 -1
  19. package/multisig/examples/ForwarderShieldedExample.compact +8 -5
  20. package/multisig/examples/ForwarderUnshieldedExample.compact +1 -1
  21. package/multisig/examples/NativeShieldedTokenIssuerExample.compact +7 -5
  22. package/multisig/examples/ShieldedMultiSigV2Example.compact +2 -2
  23. package/multisig/presets/NativeShieldedTokenIssuer.compact +47 -30
  24. package/multisig/presets/ShieldedMultiSigV2.compact +16 -7
  25. package/package.json +2 -2
  26. package/security/Allowlist.compact +1 -1
  27. package/security/Blocklist.compact +1 -1
  28. package/security/Initializable.compact +1 -1
  29. package/security/Pausable.compact +1 -1
  30. package/token/ConfidentialFungibleToken.compact +17 -1
  31. package/token/FungibleToken.compact +1 -1
  32. package/token/MultiToken.compact +1 -1
  33. package/token/NativeShieldedToken.compact +2 -2
  34. package/token/NativeShieldedTokenCore.compact +11 -18
  35. package/token/NativeShieldedTokenFamily.compact +2 -2
  36. package/token/NonFungibleToken.compact +1 -1
  37. package/token/extensions/ConfidentialFungibleTokenPublicSupply.compact +1 -1
  38. package/token/extensions/NativeShieldedTokenDerivedNonce.compact +1 -1
  39. package/utils/EvmAbi.compact +1 -1
  40. package/utils/Utils.compact +1 -1
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (access/AccessControl.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (access/AccessControl.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.4 (access/Ownable.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (access/Ownable.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.4 (access/ShieldedAccessControl.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (access/ShieldedAccessControl.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.4 (access/ZOwnablePK.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (access/ZOwnablePK.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.4 (crypto/EcdhMask.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (crypto/EcdhMask.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.4 (crypto/Ecdsa.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (crypto/Ecdsa.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.4 (crypto/Eip712.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (crypto/Eip712.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.4 (crypto/ElGamal.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (crypto/ElGamal.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.4 (multisig/EcdsaSignerManager.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/EcdsaSignerManager.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -77,13 +77,14 @@ module EcdsaSignerManager {
77
77
  * - Can only be called once.
78
78
  * - `instanceSalt` should be cryptographically random.
79
79
  * - `signerCommitments` must not contain duplicates.
80
- * - `threshold` must be non-zero and must not exceed `n`.
81
- * - `threshold` must not exceed 2, the number of approvals `assertApprovals`
82
- * verifies.
80
+ * - `n` must be at least 2, the number of distinct signers `assertApprovals`
81
+ * verifies. A smaller set can never satisfy it.
82
+ * - `threshold` must be 2, the number of approvals `assertApprovals`
83
+ * verifies. Any other value would misreport what the circuit enforces.
83
84
  *
84
85
  * @param {Bytes<32>} instanceSalt - Per-deployment salt for commitment derivation.
85
86
  * @param {Vector<n, Bytes<32>>} signerCommitments - Hashed signer identities.
86
- * @param {Uint<8>} threshold - Minimum approvals required.
87
+ * @param {Uint<8>} threshold - Approvals required. Must be 2.
87
88
  * @returns {[]} Empty tuple.
88
89
  */
89
90
  export circuit initialize<#n>(
@@ -93,11 +94,12 @@ module EcdsaSignerManager {
93
94
  ): [] {
94
95
  assert(Signer_getSignerCount() == 0, "EcdsaSignerManager: signers already registered");
95
96
  _instanceSalt = disclose(instanceSalt);
96
- assert(threshold <= 2, "EcdsaSignerManager: threshold cannot exceed 2 (assertApprovals verifies 2 signatures)");
97
+ assert(threshold == 2, "EcdsaSignerManager: threshold must be 2 (assertApprovals verifies 2 signatures)");
97
98
 
98
99
  for (const commitment of signerCommitments) {
99
100
  Signer__addSigner(commitment);
100
101
  }
102
+ assert(Signer_getSignerCount() >= 2, "EcdsaSignerManager: fewer than 2 signers (assertApprovals verifies 2 signatures)");
101
103
  Signer__changeThreshold(threshold);
102
104
  }
103
105
 
@@ -140,7 +142,7 @@ module EcdsaSignerManager {
140
142
  * same signer.
141
143
  *
142
144
  * @dev Both entries are asserted, so the count handed to the threshold check
143
- * is always 2 and a threshold below 2 admits nothing extra.
145
+ * is always 2, matching the only threshold `initialize` accepts.
144
146
  *
145
147
  * @constraints k=17, rows=64916 (zkir-v3)
146
148
  *
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (multisig/ForwarderPrivate.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/ForwarderPrivate.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.4 (multisig/ForwarderShielded.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/ForwarderShielded.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -41,6 +41,11 @@ pragma language_version >= 0.26.0;
41
41
  * coins. Forwarding to a key no one controls strands every deposit
42
42
  * permanently. The zero-key guard rejects only the all-zero key, not an
43
43
  * otherwise-unspendable one.
44
+ *
45
+ * @notice The depositor must encrypt the forwarded output to the parent's
46
+ * encryption public key, obtained off-chain. The ledger cannot check that
47
+ * key against `_parent`, so a wrong or missing key leaves the coin
48
+ * spendable by the parent but invisible to its wallet.
44
49
  */
45
50
  module ForwarderShielded {
46
51
  import CompactStandardLibrary;
@@ -103,20 +108,24 @@ module ForwarderShielded {
103
108
  * `sendImmediateShielded` to the stored parent recipient (always the
104
109
  * `left` / coin-public-key arm today).
105
110
  *
106
- * @constraints k=15, rows=24373
111
+ * @constraints k=15, rows=23197
107
112
  *
108
113
  * Requirements:
109
114
  *
110
115
  * - Contract must be initialized.
116
+ * - The forwarded output must be encrypted to the parent's encryption
117
+ * public key (see the module header). If unsure, hand the returned
118
+ * `ShieldedSendResult` to the parent so it can recover the coin.
111
119
  *
112
120
  * @param {ShieldedCoinInfo} coin - The incoming shielded coin.
113
121
  *
114
- * @returns {[]} Empty tuple.
122
+ * @returns {ShieldedSendResult} The coin sent to the parent, with no change:
123
+ * the whole value is forwarded.
115
124
  */
116
- export circuit _deposit(coin: ShieldedCoinInfo): [] {
125
+ export circuit _deposit(coin: ShieldedCoinInfo): ShieldedSendResult {
117
126
  assertInitialized();
118
127
  receiveShielded(disclose(coin));
119
- sendImmediateShielded(disclose(coin), _parent, disclose(coin.value));
128
+ return sendImmediateShielded(disclose(coin), _parent, disclose(coin.value));
120
129
  }
121
130
 
122
131
  // ─── Init guards ────────────────────────────────────────────────
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (multisig/ForwarderUnshielded.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/ForwarderUnshielded.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.4 (multisig/ProposalManager.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/ProposalManager.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.4 (multisig/ShieldedTreasury.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/ShieldedTreasury.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.4 (multisig/ShieldedTreasuryStateless.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/ShieldedTreasuryStateless.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.4 (multisig/Signer.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/Signer.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.4 (multisig/UnshieldedTreasury.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/UnshieldedTreasury.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -90,8 +90,7 @@ module UnshieldedTreasury {
90
90
  // ─── Send ───────────────────────────────────────────────────────
91
91
 
92
92
  /**
93
- * @description Sends unshielded tokens from the treasury. Zero-amount sends
94
- * are permitted and are value-preserving no-ops.
93
+ * @description Sends unshielded tokens from the treasury.
95
94
  *
96
95
  * @warning Recipients are not validated. An unspendable recipient (such as a
97
96
  * zero address) is accepted and permanently removes the funds from the
@@ -111,6 +110,7 @@ module UnshieldedTreasury {
111
110
  *
112
111
  * Requirements:
113
112
  *
113
+ * - The amount must be non-zero. The ledger rejects zero-value outputs.
114
114
  * - The treasury must hold sufficient balance for the given token color.
115
115
  *
116
116
  * @param {Either<ContractAddress, UserAddress>} recipient - The recipient address.
@@ -124,6 +124,8 @@ module UnshieldedTreasury {
124
124
  color: Bytes<32>,
125
125
  amount: Uint<128>
126
126
  ): [] {
127
+ assert(amount != 0, "UnshieldedTreasury: zero amount");
128
+
127
129
  const bal = getTokenBalance(color);
128
130
  assert(bal >= amount, "UnshieldedTreasury: insufficient balance");
129
131
 
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (multisig/examples/ForwarderPrivateExample.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/examples/ForwarderPrivateExample.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.4 (multisig/examples/ForwarderShieldedExample.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/examples/ForwarderShieldedExample.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -24,7 +24,7 @@ pragma language_version >= 0.26.0;
24
24
  import CompactStandardLibrary;
25
25
  import "../ForwarderShielded" prefix Forwarder_;
26
26
 
27
- export { ZswapCoinPublicKey, ContractAddress, ShieldedCoinInfo, Either };
27
+ export { ZswapCoinPublicKey, ContractAddress, ShieldedCoinInfo, ShieldedSendResult, Maybe, Either };
28
28
 
29
29
  /**
30
30
  * @description Deploys the forwarder bound to a specific parent
@@ -42,12 +42,15 @@ constructor(parent: ZswapCoinPublicKey) {
42
42
  * the configured parent. The coin is claimed via `receiveShielded` and
43
43
  * immediately re-sent via `sendImmediateShielded`.
44
44
  *
45
+ * The depositor must encrypt the forwarded output to the parent's
46
+ * encryption public key (see the `ForwarderShielded` header).
47
+ *
45
48
  * @param {ShieldedCoinInfo} coin - The incoming shielded coin.
46
49
  *
47
- * @returns {[]} Empty tuple.
50
+ * @returns {ShieldedSendResult} The coin sent to the parent, with no change.
48
51
  */
49
- export circuit deposit(coin: ShieldedCoinInfo): [] {
50
- Forwarder__deposit(coin);
52
+ export circuit deposit(coin: ShieldedCoinInfo): ShieldedSendResult {
53
+ return Forwarder__deposit(coin);
51
54
  }
52
55
 
53
56
  /**
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (multisig/examples/ForwarderUnshieldedExample.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/examples/ForwarderUnshieldedExample.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.4 (multisig/examples/NativeShieldedTokenIssuerExample.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/examples/NativeShieldedTokenIssuerExample.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -11,8 +11,10 @@ pragma language_version >= 0.26.0;
11
11
  * (`mintToSelf`), and leaves only through an ECDSA-authorized burn, of a
12
12
  * holder's coin (`burn`) or of one the contract holds (`burnFromSelf`).
13
13
  *
14
- * The token is non-transferable by construction. There is no transfer circuit,
15
- * so a holder's only exit is to pay the coin into a `burn` tx.
14
+ * Coins minted to holders are ordinary Zswap coins: holders transfer them
15
+ * through Zswap without the issuer's involvement and redeem by paying one
16
+ * into a `burn` tx. Only contract-held coins are locked. No send circuit
17
+ * exists, so they leave through `burnFromSelf` alone.
16
18
  */
17
19
 
18
20
  import CompactStandardLibrary;
@@ -113,7 +115,7 @@ export circuit mintToSelf(
113
115
 
114
116
  export circuit burn(
115
117
  coin: ShieldedCoinInfo,
116
- amount: Uint<64>,
118
+ amount: Uint<128>,
117
119
  refundTo: ZswapCoinPublicKey,
118
120
  pubkeys: Vector<2, Secp256k1Point>,
119
121
  signatures: Vector<2, Secp256k1EcdsaSignature>
@@ -123,7 +125,7 @@ export circuit burn(
123
125
 
124
126
  export circuit burnFromSelf(
125
127
  coin: QualifiedShieldedCoinInfo,
126
- amount: Uint<64>,
128
+ amount: Uint<128>,
127
129
  pubkeys: Vector<2, Secp256k1Point>,
128
130
  signatures: Vector<2, Secp256k1EcdsaSignature>
129
131
  ): Maybe<ShieldedCoinInfo> {
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (multisig/examples/ShieldedMultiSigV2Example.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/examples/ShieldedMultiSigV2Example.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -29,7 +29,7 @@ export { _domainSeparator };
29
29
  *
30
30
  * @param {Bytes<32>} instanceSalt - Random salt for commitment derivation.
31
31
  * @param {Vector<3, Bytes<32>>} signerCommitments - Hashed signer identities.
32
- * @param {Uint<8>} thresh - Minimum approvals required.
32
+ * @param {Uint<8>} thresh - Approvals required. Must be 2.
33
33
  */
34
34
  constructor(
35
35
  instanceSalt: Bytes<32>,
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (multisig/presets/NativeShieldedTokenIssuer.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/presets/NativeShieldedTokenIssuer.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -44,16 +44,19 @@ pragma language_version >= 0.26.0;
44
44
  * - MintToSelf digest: `keccak(0x1901 ‖ DS ‖ keccak([MINT_TO_SELF_TYPEHASH,
45
45
  * self, uint64Word(opNonce), uint64Word(amount)]))`.
46
46
  * - Burn digest: `keccak(0x1901 ‖ DS ‖ keccak([BURN_TYPEHASH, self,
47
- * refundTo.bytes, uint64Word(opNonce), uint64Word(amount)]))`.
47
+ * refundTo.bytes, uint64Word(opNonce), uint128Word(amount)]))`.
48
48
  * - BurnFromSelf digest: `keccak(0x1901 ‖ DS ‖ keccak([
49
- * BURN_FROM_SELF_TYPEHASH, self, uint64Word(opNonce), uint64Word(amount)]))`.
49
+ * BURN_FROM_SELF_TYPEHASH, self, uint64Word(opNonce), uint128Word(amount),
50
+ * coin.nonce, uint128Word(coin.value)]))`. The last two words name the
51
+ * holding, so approvals authorize one coin rather than an amount.
50
52
  * - Type hashes: `MINT_TYPEHASH = keccak("Mint(bytes32 contractAddress,
51
53
  * bytes32 recipient,uint256 nonce,uint256 amount)")`,
52
54
  * `MINT_TO_SELF_TYPEHASH = keccak("MintToSelf(bytes32 contractAddress,
53
55
  * uint256 nonce,uint256 amount)")`, `BURN_TYPEHASH = keccak("Burn(bytes32 contractAddress,bytes32 refundTo,
54
56
  * uint256 nonce,uint256 amount)")` and `BURN_FROM_SELF_TYPEHASH =
55
57
  * keccak("BurnFromSelf(bytes32 contractAddress,uint256 nonce,
56
- * uint256 amount)")`, written as literal words.
58
+ * uint256 amount,bytes32 coinNonce,uint256 coinValue)")`, written as
59
+ * literal words.
57
60
  * - Signer commitment: `cm = H<SignerCommitmentInput>({ pkX, pkY, salt,
58
61
  * domain: pad(32, "multisig:signer:") })`, `pkX` / `pkY` the affine
59
62
  * coordinates as `Bytes<32>`. `_calculateSignerId` is the exported pure
@@ -133,19 +136,22 @@ pragma language_version >= 0.26.0;
133
136
  *
134
137
  * @notice Security:
135
138
  * - Digest binding: each struct binds its type hash, `self`, `opNonce` and
136
- * `amount` (`mint` also `recipient`, `burn` also `refundTo`) under `DS`,
137
- * so a
139
+ * `amount` (`mint` also `recipient`, `burn` also `refundTo`,
140
+ * `burnFromSelf` also `coin.nonce` and `coin.value`) under `DS`, so a
138
141
  * signature authorizes one operation on one instance at one nonce, and is
139
142
  * neither replayable as another operation, nor under another domain,
140
143
  * nor redirectable. Removing the `self` word removes cross-instance
141
- * replay protection, since `DS` cannot carry the address. `Burn` does not
142
- * bind `coin`: the payer picks it, so a signature moved to another coin
143
- * burns only the payer's own value and refunds the bound `refundTo`.
144
+ * replay protection, since `DS` cannot carry the address. Only
145
+ * `burnFromSelf` binds its coin, because only there does the submitter
146
+ * pick it from the contract's own holdings. `Burn` needs no such word. Its
147
+ * coin is paid into the tx by whoever submits it so replaying a
148
+ * signature against a different coin destroys the submitter's own funds and
149
+ * still refunds the bound `refundTo`.
144
150
  * - Low-s: verification goes through `Ecdsa_secp256k1EcdsaVerifyLowS`, so a
145
151
  * high-s encoding is an invalid signature.
146
152
  * - Distinct signers: `assertApprovals` asserts both entries and rejects a
147
153
  * repeated commitment, so two distinct registered signers are always
148
- * required. The threshold `2` is the ceiling `EcdsaSignerManager` accepts.
154
+ * required. The threshold `2` is the only value `EcdsaSignerManager` accepts.
149
155
  * - Immutable signer set: no signer reconfiguration circuit is exported, so
150
156
  * the three commitments and the threshold are fixed. Losing two of the
151
157
  * three keys freezes the contract.
@@ -192,19 +198,24 @@ pragma language_version >= 0.26.0;
192
198
  * re-nonces the coin first (a wallet self-transfer yields a fresh secret
193
199
  * nonce); the minted coin as-is is valid but linkable. The contract cannot
194
200
  * enforce this.
201
+ * - `burnFromSelf` coin selection: pick the coin before collecting
202
+ * signatures, not after. Its `nonce` and `value` are in the digest, so
203
+ * signers approve one holding and the submitted coin must be that one.
195
204
  * - `burnFromSelf` coin tracking: keep contract-held coins off-chain,
196
205
  * recovering each coin's `mt_index` from the indexer's `ZswapOutput` /
197
206
  * ledger events to build the `QualifiedShieldedCoinInfo` it takes.
198
- * - `burnFromSelf` change coin: persist the one it returns. It replaces the
199
- * spent coin as the contract's holding and is not otherwise recoverable.
207
+ * - `burnFromSelf` change coin: it replaces the spent coin as the contract's
208
+ * holding. Either persist the coin the circuit returns, or rebuild it from
209
+ * the signed `coinNonce` and `coinValue`, which determine it, so recovery
210
+ * doesn't need to rest on the submitter alone. Rebuilding leans on the protocol's
211
+ * nonce derivation which this module neither defines nor pins.
200
212
  *
201
213
  * @notice Scalability:
202
214
  * - Throughput: one operation per block (see Concurrency).
203
215
  * - State: constant-size, two counters and a three-entry signer set. Nothing
204
216
  * grows per operation.
205
- * - Amounts: both mints cap at `Uint<64>` by `mintShieldedToken`; both burns
206
- * take `Uint<64>` by their signatures and widen into the module's
207
- * `Uint<128>`.
217
+ * - Amounts: mints cap at `Uint<64>` by `mintShieldedToken`. Burns take
218
+ * `Uint<128>`, the coin value range.
208
219
  *
209
220
  * @dev Composition:
210
221
  * - Recipient privacy: pass a caller-supplied secret random nonce to
@@ -361,7 +372,7 @@ module NativeShieldedTokenIssuer {
361
372
 
362
373
  /**
363
374
  * @description `keccak256` of the `BurnFromSelf` type string:
364
- * `BurnFromSelf(bytes32 contractAddress,uint256 nonce,uint256 amount)`
375
+ * `BurnFromSelf(bytes32 contractAddress,uint256 nonce,uint256 amount,bytes32 coinNonce,uint256 coinValue)`
365
376
  *
366
377
  * @dev Written as a literal word. `compactc` emits a full keccak
367
378
  * permutation even for a constant argument, so hashing the type string
@@ -372,10 +383,10 @@ module NativeShieldedTokenIssuer {
372
383
  */
373
384
  pure circuit BURN_FROM_SELF_TYPEHASH(): Bytes<32> {
374
385
  const typeHash: Vector<32, Uint<8>> = [
375
- 0x08, 0xba, 0x21, 0x80, 0x7e, 0x7f, 0x75, 0x47,
376
- 0xa2, 0x70, 0x1d, 0x8c, 0x53, 0x06, 0x39, 0x7d,
377
- 0x97, 0xad, 0xfd, 0x3e, 0xa6, 0xf6, 0xa2, 0x8c,
378
- 0x10, 0x0c, 0xbd, 0x64, 0x9c, 0x7f, 0x5d, 0x94
386
+ 0x50, 0xa1, 0xf2, 0x88, 0xba, 0xb8, 0x77, 0x4b,
387
+ 0x1f, 0x55, 0x86, 0x31, 0xc7, 0x75, 0xda, 0x49,
388
+ 0xec, 0x20, 0x4e, 0x07, 0xcf, 0x88, 0x53, 0x9b,
389
+ 0xca, 0x8e, 0xb9, 0x8c, 0xac, 0xf4, 0x5b, 0xe9
379
390
  ];
380
391
 
381
392
  return typeHash as Bytes<32>;
@@ -461,7 +472,7 @@ module NativeShieldedTokenIssuer {
461
472
  * @notice The returned coin info is the contract's only record of the
462
473
  * holding; persist it for `burnFromSelf`.
463
474
  *
464
- * @constraints k=17, rows=91259 (zkir-v3)
475
+ * @constraints k=17, rows=85594 (zkir-v3)
465
476
  *
466
477
  * Requirements:
467
478
  *
@@ -506,7 +517,7 @@ module NativeShieldedTokenIssuer {
506
517
  * @notice The returned refund coin info is the only copy available to
507
518
  * `refundTo`; deliver it out of band.
508
519
  *
509
- * @constraints k=17, rows=118642 (zkir-v3)
520
+ * @constraints k=17, rows=119826 (zkir-v3)
510
521
  *
511
522
  * Requirements:
512
523
  *
@@ -519,7 +530,7 @@ module NativeShieldedTokenIssuer {
519
530
  * - `refundTo` is not zero.
520
531
  *
521
532
  * @param {ShieldedCoinInfo} coin - The holder's coin to burn from.
522
- * @param {Uint<64>} amount - The token amount to burn.
533
+ * @param {Uint<128>} amount - The token amount to burn.
523
534
  * @param {ZswapCoinPublicKey} refundTo - Receives `coin.value - amount`.
524
535
  * @param {Vector<2, Secp256k1Point>} pubkeys - Public keys of approving signers.
525
536
  * @param {Vector<2, Secp256k1EcdsaSignature>} signatures - ECDSA signatures over the burn hash.
@@ -528,7 +539,7 @@ module NativeShieldedTokenIssuer {
528
539
  */
529
540
  export circuit burn(
530
541
  coin: ShieldedCoinInfo,
531
- amount: Uint<64>,
542
+ amount: Uint<128>,
532
543
  refundTo: ZswapCoinPublicKey,
533
544
  pubkeys: Vector<2, Secp256k1Point>,
534
545
  signatures: Vector<2, Secp256k1EcdsaSignature>
@@ -544,7 +555,7 @@ module NativeShieldedTokenIssuer {
544
555
  kernel.self().bytes,
545
556
  refundTo.bytes,
546
557
  EvmAbi_uint64Word(opNonce),
547
- EvmAbi_uint64Word(amount)
558
+ EvmAbi_uint128Word(amount)
548
559
  ]));
549
560
 
550
561
  EcdsaSignerManager_assertApprovals(msgHash, pubkeys, signatures);
@@ -561,7 +572,10 @@ module NativeShieldedTokenIssuer {
561
572
  * and returned; it replaces `coin` as the contract's holding, so the
562
573
  * operator must persist it.
563
574
  *
564
- * @constraints k=17, rows=97232 (zkir-v3)
575
+ * The digest binds `coin.nonce` and `coin.value`, so approvals authorize one
576
+ * specific holding rather than an amount.
577
+ *
578
+ * @constraints k=17, rows=104981 (zkir-v3)
565
579
  *
566
580
  * Requirements:
567
581
  *
@@ -571,9 +585,10 @@ module NativeShieldedTokenIssuer {
571
585
  * - Threshold must be met.
572
586
  * - `coin.color` is this contract's token color.
573
587
  * - `amount` is less than or equal to `coin.value`.
588
+ * - `coin.nonce` and `coin.value` match the approved coin.
574
589
  *
575
590
  * @param {QualifiedShieldedCoinInfo} coin - The contract-held coin to burn from.
576
- * @param {Uint<64>} amount - The token amount to burn.
591
+ * @param {Uint<128>} amount - The token amount to burn.
577
592
  * @param {Vector<2, Secp256k1Point>} pubkeys - Public keys of approving signers.
578
593
  * @param {Vector<2, Secp256k1EcdsaSignature>} signatures - ECDSA signatures over the burn-from-self hash.
579
594
  * @returns {Maybe<ShieldedCoinInfo>} The change coin retained by the
@@ -581,21 +596,23 @@ module NativeShieldedTokenIssuer {
581
596
  */
582
597
  export circuit burnFromSelf(
583
598
  coin: QualifiedShieldedCoinInfo,
584
- amount: Uint<64>,
599
+ amount: Uint<128>,
585
600
  pubkeys: Vector<2, Secp256k1Point>,
586
601
  signatures: Vector<2, Secp256k1EcdsaSignature>
587
602
  ): Maybe<ShieldedCoinInfo> {
588
603
  const opNonce = _counter;
589
604
  _counter.increment(1);
590
605
 
591
- const msgHash = Eip712_hashTypedData(_domainSeparator, keccak256<Vector<4, Bytes<32>>>([
606
+ const msgHash = Eip712_hashTypedData(_domainSeparator, keccak256<Vector<6, Bytes<32>>>([
592
607
  BURN_FROM_SELF_TYPEHASH(),
593
608
  // Binds the digest to this deployment. The domain cannot carry the
594
609
  // address, so removing this word removes cross-instance replay
595
610
  // protection.
596
611
  kernel.self().bytes,
597
612
  EvmAbi_uint64Word(opNonce),
598
- EvmAbi_uint64Word(amount)
613
+ EvmAbi_uint128Word(amount),
614
+ coin.nonce,
615
+ EvmAbi_uint128Word(coin.value)
599
616
  ]));
600
617
 
601
618
  EcdsaSignerManager_assertApprovals(msgHash, pubkeys, signatures);
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (multisig/presets/ShieldedMultiSigV2.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (multisig/presets/ShieldedMultiSigV2.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -82,11 +82,11 @@ module ShieldedMultiSigV2 {
82
82
  *
83
83
  * - `instanceSalt` should be cryptographically random.
84
84
  * - `signerCommitments` must not contain duplicates.
85
- * - `thresh` must be non-zero and must not exceed 2.
85
+ * - `thresh` must be 2, the number of signatures `execute` verifies.
86
86
  *
87
87
  * @param {Bytes<32>} instanceSalt - Per-deployment salt for commitment derivation.
88
88
  * @param {Vector<3, Bytes<32>>} signerCommitments - Hashed signer identities.
89
- * @param {Uint<8>} thresh - Minimum approvals required.
89
+ * @param {Uint<8>} thresh - Approvals required. Must be 2.
90
90
  * @returns {[]} Empty tuple.
91
91
  */
92
92
  export circuit initialize(
@@ -165,7 +165,10 @@ module ShieldedMultiSigV2 {
165
165
  * commitment from their public key and the instance salt, rejects duplicates,
166
166
  * and enforces the threshold.
167
167
  *
168
- * @constraints k=17, rows=104644 (zkir-v3)
168
+ * @notice `to` must be a `ShieldedUser`. A contract-addressed coin would be
169
+ * unclaimable, making the transaction malformed.
170
+ *
171
+ * @constraints k=17, rows=98977 (zkir-v3)
169
172
  *
170
173
  * Requirements:
171
174
  *
@@ -173,6 +176,7 @@ module ShieldedMultiSigV2 {
173
176
  * - Both signatures must be valid over the message hash and use the low-s
174
177
  * encoding.
175
178
  * - Signers must not be duplicates.
179
+ * - `to.kind` must be `ShieldedUser`.
176
180
  * - Coin value must be >= amount.
177
181
  *
178
182
  * @param {Proposal_Recipient} to - The recipient.
@@ -210,9 +214,14 @@ module ShieldedMultiSigV2 {
210
214
 
211
215
  EcdsaSignerManager_assertApprovals(msgHash, pubkeys, signatures);
212
216
 
213
- // Execute transfer
214
- const normalizedRecipient = Proposal_toShieldedRecipient(to);
215
- return Treasury__send(coin, normalizedRecipient, amount);
217
+ assert(
218
+ to.kind == Proposal_RecipientKind.ShieldedUser,
219
+ "Multisig: recipient must be a coin public key"
220
+ );
221
+ const recipient = left<ZswapCoinPublicKey, ContractAddress>(
222
+ ZswapCoinPublicKey { bytes: to.address }
223
+ );
224
+ return Treasury__send(coin, recipient, amount);
216
225
  }
217
226
 
218
227
  // ─── Commitments ────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openzeppelin/compact-contracts",
3
- "version": "0.4.0-alpha.4",
3
+ "version": "0.4.0-alpha.5",
4
4
  "description": "OpenZeppelin Compact contract library",
5
5
  "keywords": [
6
6
  "openzeppelin",
@@ -65,7 +65,7 @@
65
65
  "@noble/curves": "^2.2.0",
66
66
  "@noble/hashes": "^2.4.0",
67
67
  "@openzeppelin/compact-deployer": "^0.3.1",
68
- "@openzeppelin/compact-simulator": "^0.4.0",
68
+ "@openzeppelin/compact-simulator": "^0.4.1",
69
69
  "@tsconfig/node24": "^24.0.5",
70
70
  "@types/node": "26.6.2",
71
71
  "@vitest/coverage-v8": "^5.0.0",
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (security/Allowlist.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (security/Allowlist.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.4 (security/Blocklist.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (security/Blocklist.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.4 (security/Initializable.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (security/Initializable.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.4 (security/Pausable.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (security/Pausable.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.4 (token/ConfidentialFungibleToken.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (token/ConfidentialFungibleToken.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -242,6 +242,22 @@ pragma language_version >= 0.26.0;
242
242
  * Raising the limit itself is a node-side change, tracked upstream:
243
243
  * https://github.com/midnightntwrk/midnight-node/issues/1202.
244
244
  *
245
+ * Upgrades. Add operations, never change how existing state is derived or laid
246
+ * out. A CMA upgrade swaps verifier keys on an instance whose ledger already
247
+ * holds data so whatever that data was written under has to stay fixed e.g. slot
248
+ * indices, nonce and key derivation, stored encodings. Slot changes at least
249
+ * show up in a diff. Key derivation is the quiet one. `_encryptionKeys` holds
250
+ * the key `derivePk` returned at `register` time, `register` refuses a second
251
+ * key for an account id, and the id does not move (untagged by design, see
252
+ * `Utils.computeAccountId`), so a circuit deriving a different key leaves
253
+ * `assertDecryptsTo` and `_assertOwnsEncryptionKey` rejecting the stored one
254
+ * with no way to re-register. This means balances, pending balances, escrow and
255
+ * memos are all permanently unreachable. An instance's derivation is fixed when
256
+ * it is deployed, so off-chain code mirroring `derivePk` must use that one for
257
+ * the life of the instance. Adopting a newer derivation cannot recover an
258
+ * instance whose keys were stored under the old one. A changed derivation
259
+ * applies to fresh deployments only.
260
+ *
245
261
  * Residual griefing. The dual-balance split (see `sweep`) stops dust
246
262
  * credits from churning a victim's spendable ciphertext, but every `_credit`
247
263
  * still appends a memo, and only the recipient can `clearMemos`. An attacker
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (token/FungibleToken.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (token/FungibleToken.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.4 (token/MultiToken.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (token/MultiToken.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.4 (token/NativeShieldedToken.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (token/NativeShieldedToken.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -232,7 +232,7 @@ module NativeShieldedToken {
232
232
  * ledger state: it is the contract's holding and is not otherwise
233
233
  * recoverable.
234
234
  *
235
- * @constraints k=14, rows=16033
235
+ * @constraints k=14, rows=10221
236
236
  *
237
237
  * Requirements:
238
238
  *
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (token/NativeShieldedTokenCore.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (token/NativeShieldedTokenCore.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -51,9 +51,10 @@ pragma language_version >= 0.26.0;
51
51
  * The ledger accepts a contract-addressed commitment only if the recipient
52
52
  * contract's own call claims it as a shielded receive in the same transaction,
53
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
54
+ * address arm is accepted only for `kernel.self()`, which `mintShieldedToken`
55
+ * and `sendShielded` claim as a receive themselves. A `receiveShielded` on top
56
+ * emits a duplicate output for the same commitment. The flavors do not expose
57
+ * the arm at all: they take a `ZswapCoinPublicKey` and offer `_mintToSelf` for
57
58
  * contract-held coins.
58
59
  *
59
60
  * @dev Burn variants
@@ -235,7 +236,7 @@ module NativeShieldedTokenCore {
235
236
  * @dev The caller is fully responsible for nonce uniqueness. Reusing a
236
237
  * nonce for the same (domain, value, recipient) produces a duplicate
237
238
  * commitment, which the protocol rejects. A `right(kernel.self())` recipient
238
- * is claimed via `receiveShielded` in this same call, so the consumer SHOULD
239
+ * is claimed by `mintShieldedToken` in this same call, so the consumer SHOULD
239
240
  * persist the returned coin info: it is the contract's holding and is not
240
241
  * otherwise recoverable.
241
242
  *
@@ -243,7 +244,7 @@ module NativeShieldedTokenCore {
243
244
  * recipient; callers SHOULD deliver it out of band. Wallets cannot detect
244
245
  * contract-minted coins by scanning the chain.
245
246
  *
246
- * @constraints k=15, rows=16980
247
+ * @constraints k=14, rows=11109
247
248
  *
248
249
  * Requirements:
249
250
  *
@@ -269,12 +270,7 @@ module NativeShieldedTokenCore {
269
270
  assert(!Utils_isKeyOrAddressZero(recipient), "NativeShieldedToken: invalid recipient");
270
271
  assert(recipient.is_left || recipient.right == self, "NativeShieldedToken: recipient contract must be self");
271
272
 
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;
273
+ return mintShieldedToken(disclose(domain), disclose(amount), disclose(nonce), disclose(recipient));
278
274
  }
279
275
 
280
276
  /**
@@ -289,14 +285,14 @@ module NativeShieldedTokenCore {
289
285
  * @dev The coin is received by the contract and spent in the same
290
286
  * transaction, so the spend goes through `sendImmediateShielded` (the
291
287
  * transient path). For coins the contract already holds, use
292
- * `_burnFromSelf` instead. A `right(kernel.self())` refund is claimed via
293
- * `receiveShielded` in this same call.
288
+ * `_burnFromSelf` instead. A `right(kernel.self())` refund is claimed by
289
+ * `sendImmediateShielded` in this same call.
294
290
  *
295
291
  * @notice The returned refund coin info is the only copy available to
296
292
  * `refundTo`; callers SHOULD deliver it out of band. Wallets cannot detect
297
293
  * contract-sent coins by scanning the chain.
298
294
  *
299
- * @constraints k=16, rows=53639
295
+ * @constraints k=16, rows=47764
300
296
  *
301
297
  * Requirements:
302
298
  *
@@ -338,9 +334,6 @@ module NativeShieldedTokenCore {
338
334
  disclose(refundTo),
339
335
  disclose(sendRes.change.value.value)
340
336
  );
341
- if (disclose(!refundTo.is_left)) {
342
- receiveShielded(refundRes.sent);
343
- }
344
337
  return some<ShieldedCoinInfo>(refundRes.sent);
345
338
  }
346
339
  return none<ShieldedCoinInfo>();
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (token/NativeShieldedTokenFamily.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (token/NativeShieldedTokenFamily.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5
 
@@ -230,7 +230,7 @@ module NativeShieldedTokenFamily {
230
230
  * ledger state: it is the contract's holding and is not otherwise
231
231
  * recoverable.
232
232
  *
233
- * @constraints k=14, rows=16309
233
+ * @constraints k=14, rows=10497
234
234
  *
235
235
  * Requirements:
236
236
  *
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Compact Contracts v0.4.0-alpha.4 (token/NonFungibleToken.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (token/NonFungibleToken.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.4 (token/extensions/ConfidentialFungibleTokenPublicSupply.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (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.4 (token/extensions/NativeShieldedTokenDerivedNonce.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (token/extensions/NativeShieldedTokenDerivedNonce.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.4 (utils/EvmAbi.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (utils/EvmAbi.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.4 (utils/Utils.compact)
2
+ // OpenZeppelin Compact Contracts v0.4.0-alpha.5 (utils/Utils.compact)
3
3
 
4
4
  pragma language_version >= 0.26.0;
5
5