@lfdecentralizedtrust/zeto-contracts 0.2.2 → 0.5.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.
Files changed (152) hide show
  1. package/README.md +70 -162
  2. package/contracts/factory.sol +30 -34
  3. package/contracts/factory_upgradeable.sol +11 -7
  4. package/contracts/lib/common/util.sol +40 -0
  5. package/contracts/lib/interfaces/ILockableCapability.sol +318 -0
  6. package/contracts/lib/interfaces/{izeto.sol → IZeto.sol} +13 -1
  7. package/contracts/lib/interfaces/{izeto_initializable.sol → IZetoInitializable.sol} +14 -12
  8. package/contracts/lib/interfaces/{izeto_kyc.sol → IZetoKyc.sol} +3 -3
  9. package/contracts/lib/interfaces/IZetoLockableCapability.sol +237 -0
  10. package/contracts/lib/interfaces/IZetoStorage.sol +106 -0
  11. package/contracts/lib/interfaces/{izeto_lockable.sol → IZetoVerifier.sol} +8 -21
  12. package/contracts/lib/registry.sol +74 -26
  13. package/contracts/lib/storage/base.sol +210 -0
  14. package/contracts/lib/storage/nullifier.sol +166 -0
  15. package/contracts/lib/zeto_common.sol +277 -28
  16. package/contracts/lib/zeto_fungible.sol +451 -33
  17. package/contracts/lib/zeto_fungible_base.sol +69 -0
  18. package/contracts/lib/zeto_fungible_burn.sol +83 -53
  19. package/contracts/lib/zeto_fungible_burn_nullifier.sol +115 -72
  20. package/contracts/lib/zeto_fungible_nullifier.sol +167 -0
  21. package/contracts/lib/zeto_lockable.sol +613 -0
  22. package/contracts/lib/zeto_non_fungible.sol +236 -0
  23. package/contracts/lib/zeto_non_fungible_base.sol +61 -0
  24. package/contracts/lib/zeto_non_fungible_nullifier.sol +61 -0
  25. package/contracts/test/escrow1.sol +90 -34
  26. package/contracts/test/escrow2.sol +64 -29
  27. package/contracts/test/qurrency.sol +10 -2
  28. package/contracts/test/smt.sol +6 -1
  29. package/contracts/test/tendecimals.sol +14 -12
  30. package/contracts/verifiers/impl/anon.sol +189 -0
  31. package/contracts/verifiers/impl/anon_batch.sol +301 -0
  32. package/contracts/verifiers/impl/anon_enc.sol +266 -0
  33. package/contracts/verifiers/impl/anon_enc_batch.sol +602 -0
  34. package/contracts/verifiers/impl/anon_enc_nullifier.sol +287 -0
  35. package/contracts/verifiers/impl/anon_enc_nullifier_batch.sol +679 -0
  36. package/contracts/verifiers/impl/anon_enc_nullifier_kyc.sol +294 -0
  37. package/contracts/verifiers/impl/anon_enc_nullifier_kyc_batch.sol +686 -0
  38. package/contracts/verifiers/impl/anon_enc_nullifier_non_repudiation.sol +413 -0
  39. package/contracts/verifiers/impl/anon_enc_nullifier_non_repudiation_batch.sol +1141 -0
  40. package/contracts/verifiers/impl/anon_nullifier_kyc_transfer.sol +217 -0
  41. package/contracts/verifiers/impl/anon_nullifier_kyc_transferLocked.sol +196 -0
  42. package/contracts/verifiers/impl/anon_nullifier_kyc_transferLocked_batch.sol +308 -0
  43. package/contracts/verifiers/impl/anon_nullifier_kyc_transfer_batch.sol +385 -0
  44. package/contracts/verifiers/impl/anon_nullifier_qurrency_transfer.sol +497 -0
  45. package/contracts/verifiers/impl/anon_nullifier_qurrency_transfer_batch.sol +1001 -0
  46. package/contracts/verifiers/{verifier_anon_nullifier_transferLocked.sol → impl/anon_nullifier_transfer.sol} +12 -19
  47. package/contracts/verifiers/{verifier_anon_nullifier_transferLocked_batch.sol → impl/anon_nullifier_transfer_batch.sol} +44 -51
  48. package/contracts/verifiers/impl/burn.sol +182 -0
  49. package/contracts/verifiers/impl/burn_batch.sol +238 -0
  50. package/contracts/verifiers/impl/burn_nullifier.sol +203 -0
  51. package/contracts/verifiers/impl/burn_nullifier_batch.sol +315 -0
  52. package/contracts/verifiers/impl/deposit.sol +182 -0
  53. package/contracts/verifiers/impl/deposit_kyc.sol +189 -0
  54. package/contracts/verifiers/impl/nf_anon.sol +175 -0
  55. package/contracts/verifiers/{verifier_nf_anon_nullifier_transferLocked.sol → impl/nf_anon_nullifier_transfer.sol} +6 -13
  56. package/contracts/verifiers/impl/withdraw.sol +189 -0
  57. package/contracts/verifiers/impl/withdraw_batch.sol +245 -0
  58. package/contracts/verifiers/impl/withdraw_nullifier.sol +210 -0
  59. package/contracts/verifiers/impl/withdraw_nullifier_batch.sol +322 -0
  60. package/contracts/verifiers/verifier_anon.sol +31 -186
  61. package/contracts/verifiers/verifier_anon_batch.sol +31 -298
  62. package/contracts/verifiers/verifier_anon_enc.sol +31 -263
  63. package/contracts/verifiers/verifier_anon_enc_batch.sol +31 -599
  64. package/contracts/verifiers/verifier_anon_enc_nullifier.sol +31 -284
  65. package/contracts/verifiers/verifier_anon_enc_nullifier_batch.sol +33 -676
  66. package/contracts/verifiers/verifier_anon_enc_nullifier_kyc.sol +31 -291
  67. package/contracts/verifiers/verifier_anon_enc_nullifier_kyc_batch.sol +33 -683
  68. package/contracts/verifiers/verifier_anon_enc_nullifier_non_repudiation.sol +33 -410
  69. package/contracts/verifiers/verifier_anon_enc_nullifier_non_repudiation_batch.sol +33 -1138
  70. package/contracts/verifiers/verifier_anon_nullifier_kyc_transfer.sol +33 -214
  71. package/contracts/verifiers/verifier_anon_nullifier_kyc_transferLocked.sol +33 -221
  72. package/contracts/verifiers/verifier_anon_nullifier_kyc_transferLocked_batch.sol +33 -389
  73. package/contracts/verifiers/verifier_anon_nullifier_kyc_transfer_batch.sol +33 -382
  74. package/contracts/verifiers/verifier_anon_nullifier_qurrency_transfer.sol +33 -221
  75. package/contracts/verifiers/verifier_anon_nullifier_qurrency_transfer_batch.sol +33 -389
  76. package/contracts/verifiers/verifier_anon_nullifier_transfer.sol +33 -207
  77. package/contracts/verifiers/verifier_anon_nullifier_transfer_batch.sol +33 -375
  78. package/contracts/verifiers/verifier_burn.sol +31 -179
  79. package/contracts/verifiers/verifier_burn_batch.sol +31 -235
  80. package/contracts/verifiers/verifier_burn_nullifier.sol +31 -200
  81. package/contracts/verifiers/verifier_burn_nullifier_batch.sol +31 -312
  82. package/contracts/verifiers/verifier_deposit.sol +31 -179
  83. package/contracts/verifiers/verifier_deposit_kyc.sol +34 -0
  84. package/contracts/verifiers/verifier_nf_anon.sol +31 -172
  85. package/contracts/verifiers/verifier_nf_anon_nullifier_transfer.sol +33 -179
  86. package/contracts/verifiers/verifier_withdraw.sol +31 -186
  87. package/contracts/verifiers/verifier_withdraw_batch.sol +31 -242
  88. package/contracts/verifiers/verifier_withdraw_nullifier.sol +31 -207
  89. package/contracts/verifiers/verifier_withdraw_nullifier_batch.sol +33 -319
  90. package/contracts/zeto_anon.sol +77 -231
  91. package/contracts/zeto_anon_burnable.sol +56 -12
  92. package/contracts/zeto_anon_enc.sol +93 -190
  93. package/contracts/zeto_anon_enc_nullifier.sol +249 -195
  94. package/contracts/zeto_anon_enc_nullifier_kyc.sol +51 -232
  95. package/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +231 -238
  96. package/contracts/zeto_anon_nullifier.sol +164 -298
  97. package/contracts/zeto_anon_nullifier_burnable.sol +68 -18
  98. package/contracts/zeto_anon_nullifier_kyc.sol +40 -345
  99. package/contracts/zeto_anon_nullifier_qurrency.sol +217 -361
  100. package/contracts/zeto_nf_anon.sol +55 -130
  101. package/contracts/zeto_nf_anon_nullifier.sol +90 -152
  102. package/hardhat.config.ts +9 -3
  103. package/ignition/modules/lib/deps.ts +8 -0
  104. package/ignition/modules/zeto_anon_burnable.ts +8 -7
  105. package/ignition/modules/zeto_anon_enc_nullifier.ts +31 -0
  106. package/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +2 -2
  107. package/ignition/modules/zeto_anon_nullifier.ts +28 -4
  108. package/ignition/modules/zeto_anon_nullifier_burnable.ts +50 -16
  109. package/ignition/modules/zeto_anon_nullifier_kyc.ts +27 -12
  110. package/ignition/modules/zeto_nf_anon_nullifier.ts +14 -10
  111. package/package.json +4 -2
  112. package/scripts/deploy_cloneable.ts +19 -10
  113. package/scripts/deploy_upgradeable.ts +9 -5
  114. package/scripts/tokens/Zeto_Anon.ts +3 -3
  115. package/scripts/tokens/Zeto_AnonBurnable.ts +1 -1
  116. package/scripts/tokens/Zeto_AnonEnc.ts +12 -3
  117. package/scripts/tokens/Zeto_AnonEncNullifier.ts +5 -3
  118. package/scripts/tokens/Zeto_AnonEncNullifierKyc.ts +1 -1
  119. package/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts +1 -1
  120. package/scripts/tokens/Zeto_AnonNullifier.ts +1 -1
  121. package/scripts/tokens/Zeto_AnonNullifierBurnable.ts +1 -1
  122. package/scripts/tokens/Zeto_AnonNullifierKyc.ts +1 -1
  123. package/scripts/tokens/Zeto_AnonNullifierQurrency.ts +1 -1
  124. package/scripts/tokens/Zeto_NfAnon.ts +2 -2
  125. package/scripts/tokens/Zeto_NfAnonNullifier.ts +1 -1
  126. package/test/factory.ts +46 -73
  127. package/test/lib/anon_nullifier_helpers.ts +89 -0
  128. package/test/lib/anon_zeto_helpers.ts +76 -0
  129. package/test/lib/deploy.ts +3 -2
  130. package/test/lib/utils.ts +74 -35
  131. package/test/test/escrow1.ts +185 -58
  132. package/test/test/escrow2.ts +200 -107
  133. package/test/test/qurrency.ts +13 -33
  134. package/test/usdc-shielding.ts +39 -26
  135. package/test/utils.ts +144 -21
  136. package/test/zeto_anon.ts +956 -465
  137. package/test/zeto_anon_enc.ts +881 -142
  138. package/test/zeto_anon_enc_nullifier.ts +847 -38
  139. package/test/zeto_anon_enc_nullifier_kyc.ts +120 -181
  140. package/test/zeto_anon_enc_nullifier_non_repudiation.ts +77 -46
  141. package/test/zeto_anon_nullifier.ts +1212 -953
  142. package/test/zeto_anon_nullifier_kyc.ts +674 -655
  143. package/test/zeto_anon_nullifier_qurrency.ts +452 -306
  144. package/test/zeto_nf_anon.ts +737 -137
  145. package/test/zeto_nf_anon_nullifier.ts +876 -246
  146. package/contracts/lib/zeto_base.sol +0 -293
  147. package/contracts/lib/zeto_fungible_withdraw.sol +0 -132
  148. package/contracts/lib/zeto_fungible_withdraw_nullifier.sol +0 -144
  149. package/contracts/lib/zeto_nullifier.sol +0 -340
  150. package/contracts/zkDvP.sol_ +0 -273
  151. package/test/zkDvP.ts_ +0 -455
  152. /package/contracts/lib/{common.sol → common/common.sol} +0 -0
@@ -15,245 +15,299 @@
15
15
  // limitations under the License.
16
16
  pragma solidity ^0.8.27;
17
17
 
18
- import {IZeto} from "./lib/interfaces/izeto.sol";
19
- import {Groth16Verifier_Deposit} from "./verifiers/verifier_deposit.sol";
20
- import {Groth16Verifier_WithdrawNullifier} from "./verifiers/verifier_withdraw_nullifier.sol";
21
- import {Groth16Verifier_WithdrawNullifierBatch} from "./verifiers/verifier_withdraw_nullifier_batch.sol";
22
- import {Groth16Verifier_AnonEncNullifier} from "./verifiers/verifier_anon_enc_nullifier.sol";
23
- import {Groth16Verifier_AnonEncNullifierBatch} from "./verifiers/verifier_anon_enc_nullifier_batch.sol";
24
- import {ZetoNullifier} from "./lib/zeto_nullifier.sol";
25
- import {ZetoFungibleWithdrawWithNullifiers} from "./lib/zeto_fungible_withdraw_nullifier.sol";
26
- import {Commonlib} from "./lib/common.sol";
27
- import {IZetoInitializable} from "./lib/interfaces/izeto_initializable.sol";
28
- import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
18
+ import {Zeto_AnonNullifier} from "./zeto_anon_nullifier.sol";
19
+ import {Commonlib} from "./lib/common/common.sol";
20
+ import {IZetoInitializable} from "./lib/interfaces/IZetoInitializable.sol";
29
21
 
30
- uint256 constant INPUT_SIZE = 18;
31
- uint256 constant BATCH_INPUT_SIZE = 74;
32
-
33
- /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking
22
+ /// @title A sample implementation of a Zeto based fungible token with
23
+ /// anonymity, encryption, and history masking via nullifiers.
34
24
  /// @author Kaleido, Inc.
25
+ /// @notice Decimals: this token uses **4** decimals, inherited from
26
+ /// {ZetoCommon.decimals}. Indexers and UIs reading this contract
27
+ /// directly should treat balances accordingly.
35
28
  /// @dev The proof has the following statements:
36
29
  /// - each value in the output commitments must be a positive number in the range 0 ~ (2\*\*40 - 1)
37
30
  /// - the sum of the nullified values match the sum of output values
38
31
  /// - the hashes in the input and output match the hash(value, salt, owner public key) formula
39
32
  /// - the sender possesses the private BabyJubjub key, whose public key is part of the pre-image of the input commitment hashes, which match the corresponding nullifiers
40
- /// - the encrypted value in the input is derived from the receiver's UTXO value and encrypted with a shared secret using the ECDH protocol between the sender and receiver (this guarantees data availability for the receiver)
33
+ /// - the encrypted value in the output is derived from the receiver's UTXO value and encrypted with a shared secret using the ECDH protocol between the sender and receiver
41
34
  /// - the nullifiers represent input commitments that are included in a Sparse Merkle Tree represented by the root hash
42
- contract Zeto_AnonEncNullifier is
43
- IZeto,
44
- IZetoInitializable,
45
- ZetoNullifier,
46
- ZetoFungibleWithdrawWithNullifiers,
47
- UUPSUpgradeable
48
- {
49
- Groth16Verifier_AnonEncNullifier internal _verifier;
50
- Groth16Verifier_AnonEncNullifierBatch internal _batchVerifier;
35
+ contract Zeto_AnonEncNullifier is Zeto_AnonNullifier {
36
+ /// @dev Decoded proof payload for one `constructPublicInputs` call lives in
37
+ /// {ZetoAnonEncNullifierStorage} (ERC-7201).
38
+
39
+ /// @dev Lock the implementation contract on construction. The parent
40
+ /// {Zeto_AnonNullifier} already does this via its own constructor
41
+ /// (which Solidity invokes as part of every leaf's deployment),
42
+ /// but we restate it here so the H-2 protection survives any
43
+ /// future refactor that changes the inheritance graph.
44
+ /// @custom:oz-upgrades-unsafe-allow constructor
45
+ constructor() {
46
+ _disableInitializers();
47
+ }
51
48
 
52
49
  function initialize(
53
- string memory name,
54
- string memory symbol,
50
+ string calldata name,
51
+ string calldata symbol,
55
52
  address initialOwner,
56
53
  IZetoInitializable.VerifiersInfo calldata verifiers
57
- ) public initializer {
58
- __ZetoNullifier_init(name, symbol, initialOwner);
59
- __ZetoFungibleWithdrawWithNullifiers_init(
60
- (Groth16Verifier_Deposit)(verifiers.depositVerifier),
61
- (Groth16Verifier_WithdrawNullifier)(verifiers.withdrawVerifier),
62
- (Groth16Verifier_WithdrawNullifierBatch)(
63
- verifiers.batchWithdrawVerifier
64
- )
65
- );
66
- _verifier = (Groth16Verifier_AnonEncNullifier)(verifiers.verifier);
67
- _batchVerifier = (Groth16Verifier_AnonEncNullifierBatch)(
68
- verifiers.batchVerifier
69
- );
54
+ ) public virtual override initializer {
55
+ __ZetoAnonEncNullifier_init(name, symbol, initialOwner, verifiers);
70
56
  }
71
57
 
72
- function _authorizeUpgrade(address) internal override onlyOwner {}
58
+ function __ZetoAnonEncNullifier_init(
59
+ string calldata name_,
60
+ string calldata symbol_,
61
+ address initialOwner,
62
+ IZetoInitializable.VerifiersInfo calldata verifiers
63
+ ) internal onlyInitializing {
64
+ __ZetoAnonNullifier_init(name_, symbol_, initialOwner, verifiers);
65
+ }
73
66
 
74
- function constructPublicInputs(
67
+ function emitTransferEvent(
75
68
  uint256[] memory nullifiers,
76
69
  uint256[] memory outputs,
77
- uint256 root,
78
- uint256 encryptionNonce,
79
- uint256[2] memory ecdhPublicKey,
80
- uint256[] memory encryptedValues,
81
- uint256 size
82
- ) internal pure returns (uint256[] memory publicInputs) {
83
- publicInputs = new uint256[](size);
84
- uint256 piIndex = 0;
85
- // copy the ecdh public key
86
- for (uint256 i = 0; i < ecdhPublicKey.length; ++i) {
87
- publicInputs[piIndex++] = ecdhPublicKey[i];
88
- }
89
- // copy the encrypted value, salt and parity bit
90
- for (uint256 i = 0; i < encryptedValues.length; ++i) {
91
- publicInputs[piIndex++] = encryptedValues[i];
92
- }
93
- // copy input commitments
94
- for (uint256 i = 0; i < nullifiers.length; i++) {
95
- publicInputs[piIndex++] = nullifiers[i];
96
- }
97
-
98
- // copy root
99
- publicInputs[piIndex++] = root;
100
-
101
- // populate enables
102
- for (uint256 i = 0; i < nullifiers.length; i++) {
103
- publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1;
104
- }
105
-
106
- // copy output commitments
107
- for (uint256 i = 0; i < outputs.length; i++) {
108
- publicInputs[piIndex++] = outputs[i];
109
- }
110
-
111
- // copy encryption nonce
112
- publicInputs[piIndex++] = encryptionNonce;
113
- return publicInputs;
70
+ bytes memory proof,
71
+ bytes memory data
72
+ ) internal virtual override {
73
+ ZetoAnonEncNullifierStorage.DecodedProofEncNullifier memory dp;
74
+ (dp, ) = decodeProof_EncNullifier(proof);
75
+ emit UTXOTransferWithEncryptedValues(
76
+ nullifiers,
77
+ outputs,
78
+ dp.encryptionNonce,
79
+ dp.ecdhPublicKey,
80
+ dp.encryptedValues,
81
+ msg.sender,
82
+ data
83
+ );
114
84
  }
115
85
 
116
86
  /**
117
- * @dev the main function of the contract, which transfers values from one account (represented by Babyjubjub public keys)
118
- * to one or more receiver accounts (also represented by Babyjubjub public keys). One of the two nullifiers may be zero
119
- * if the transaction only needs one UTXO to be spent. Equally one of the two outputs may be zero if the transaction
120
- * only needs to create one new UTXO.
87
+ * @dev Layout of `proof` (ABI-encoded tuple):
88
+ * (uint256 root,
89
+ * uint256 encryptionNonce,
90
+ * uint256[2] ecdhPublicKey,
91
+ * uint256[] encryptedValues,
92
+ * Commonlib.Proof groth16Proof)
121
93
  *
122
- * @param nullifiers Array of nullifiers that are secretly bound to UTXOs to be spent by the transaction.
123
- * @param outputs Array of new UTXOs to generate, for future transactions to spend.
124
- * @param root The root hash of the Sparse Merkle Tree that contains the nullifiers.
125
- * @param proof A zero knowledge proof that the submitter is authorized to spend the inputs, and
126
- * that the outputs are valid in terms of obeying mass conservation rules.
127
- *
128
- * Emits a {UTXOTransferWithEncryptedValues} event.
94
+ * Root validation is performed here whenever inputs are unlocked
95
+ * so the proof bytes are decoded exactly once per transition
96
+ * (mirrors the L-4 cleanup applied to {Zeto_AnonNullifier}).
129
97
  */
130
- function transfer(
98
+ function constructPublicInputs(
131
99
  uint256[] memory nullifiers,
132
100
  uint256[] memory outputs,
133
- uint256 root,
134
- uint256 encryptionNonce,
135
- uint256[2] memory ecdhPublicKey,
136
- uint256[] memory encryptedValues,
137
- Commonlib.Proof calldata proof,
138
- bytes calldata data
139
- ) public returns (bool) {
140
- // Check and pad commitments
141
- nullifiers = checkAndPadCommitments(nullifiers);
142
- outputs = checkAndPadCommitments(outputs);
143
- validateTransactionProposal(nullifiers, outputs, root, false);
101
+ bytes memory proof,
102
+ bool inputsLocked
103
+ )
104
+ internal
105
+ virtual
106
+ override
107
+ returns (uint256[] memory, Commonlib.Proof memory)
108
+ {
109
+ (
110
+ ZetoAnonEncNullifierStorage.DecodedProofEncNullifier memory dp,
111
+ Commonlib.Proof memory proofStruct
112
+ ) = decodeProof_EncNullifier(proof);
144
113
 
145
- // Check the proof
146
- if (nullifiers.length > 2 || outputs.length > 2) {
147
- uint256[] memory publicInputs = constructPublicInputs(
148
- nullifiers,
149
- outputs,
150
- root,
151
- encryptionNonce,
152
- ecdhPublicKey,
153
- encryptedValues,
154
- BATCH_INPUT_SIZE
155
- );
156
- // construct the public inputs for batchVerifier
157
- uint256[BATCH_INPUT_SIZE] memory fixedSizeInputs;
158
- for (uint256 i = 0; i < fixedSizeInputs.length; i++) {
159
- fixedSizeInputs[i] = publicInputs[i];
160
- }
114
+ if (!inputsLocked) {
115
+ validateRoot(dp.root);
116
+ }
117
+
118
+ ZetoAnonEncNullifierStorage.layout().dpe = dp;
119
+
120
+ uint256[] memory extra = extraInputs();
121
+ uint256 size = _calcSize_EncNullifier(
122
+ nullifiers,
123
+ outputs,
124
+ extra,
125
+ inputsLocked
126
+ );
161
127
 
162
- // Check the proof using batchVerifier
163
- require(
164
- _batchVerifier.verifyProof(
165
- proof.pA,
166
- proof.pB,
167
- proof.pC,
168
- fixedSizeInputs
169
- ),
170
- "Invalid proof (batch)"
128
+ uint256[] memory publicInputs = new uint256[](size);
129
+ _fillPublicInputs_EncNullifier(
130
+ publicInputs,
131
+ nullifiers,
132
+ outputs,
133
+ extra,
134
+ inputsLocked
135
+ );
136
+ return (publicInputs, proofStruct);
137
+ }
138
+
139
+ function decodeProof_EncNullifier(
140
+ bytes memory proof
141
+ )
142
+ private
143
+ pure
144
+ returns (
145
+ ZetoAnonEncNullifierStorage.DecodedProofEncNullifier memory,
146
+ Commonlib.Proof memory
147
+ )
148
+ {
149
+ (
150
+ uint256 root,
151
+ uint256 encryptionNonce,
152
+ uint256[2] memory ecdhPublicKey,
153
+ uint256[] memory encryptedValues,
154
+ Commonlib.Proof memory proofStruct
155
+ ) = abi.decode(
156
+ proof,
157
+ (uint256, uint256, uint256[2], uint256[], Commonlib.Proof)
171
158
  );
172
- } else {
173
- uint256[] memory publicInputs = constructPublicInputs(
174
- nullifiers,
175
- outputs,
159
+ return (
160
+ ZetoAnonEncNullifierStorage.DecodedProofEncNullifier(
176
161
  root,
177
162
  encryptionNonce,
178
163
  ecdhPublicKey,
179
- encryptedValues,
180
- INPUT_SIZE
164
+ encryptedValues
165
+ ),
166
+ proofStruct
167
+ );
168
+ }
169
+
170
+ /// @dev Public-inputs vector size. For unlocked spends the layout is
171
+ /// ecdhPublicKey ++ encryptedValues ++ nullifiers ++ root
172
+ /// ++ enabled-flags ++ extra ++ outputs ++ encryptionNonce
173
+ /// For locked-input spends the nullifier-history (root + flags)
174
+ /// portion of the witness is absent because locked inputs are
175
+ /// raw UTXOs, not nullifiers; the encryption commitments and the
176
+ /// output commitments still apply.
177
+ function _calcSize_EncNullifier(
178
+ uint256[] memory nullifiers,
179
+ uint256[] memory outputs,
180
+ uint256[] memory extra,
181
+ bool inputsLocked
182
+ ) internal view returns (uint256) {
183
+ if (inputsLocked) {
184
+ return
185
+ ZetoAnonEncNullifierStorage.layout().dpe.ecdhPublicKey.length +
186
+ ZetoAnonEncNullifierStorage.layout().dpe.encryptedValues.length +
187
+ nullifiers.length +
188
+ extra.length +
189
+ outputs.length +
190
+ 1; // encryptionNonce
191
+ }
192
+ return
193
+ ZetoAnonEncNullifierStorage.layout().dpe.ecdhPublicKey.length +
194
+ ZetoAnonEncNullifierStorage.layout().dpe.encryptedValues.length +
195
+ (nullifiers.length * 2) + // nullifiers + enabled flags
196
+ 1 + // root
197
+ extra.length +
198
+ outputs.length +
199
+ 1; // encryptionNonce
200
+ }
201
+
202
+ function _fillPublicInputs_EncNullifier(
203
+ uint256[] memory publicInputs,
204
+ uint256[] memory nullifiers,
205
+ uint256[] memory outputs,
206
+ uint256[] memory extra,
207
+ bool inputsLocked
208
+ ) internal view {
209
+ uint256 piIndex = 0;
210
+ piIndex = _fillEcdhAndEncrypted(publicInputs, piIndex);
211
+ if (!inputsLocked) {
212
+ piIndex = _fillNullifiersAndRoot(publicInputs, nullifiers, piIndex);
213
+ piIndex = _fillEnablesAndExtra(
214
+ publicInputs,
215
+ nullifiers,
216
+ extra,
217
+ piIndex
181
218
  );
182
- // construct the public inputs for verifier
183
- uint256[INPUT_SIZE] memory fixedSizeInputs;
184
- for (uint256 i = 0; i < fixedSizeInputs.length; i++) {
185
- fixedSizeInputs[i] = publicInputs[i];
219
+ } else {
220
+ for (uint256 i = 0; i < nullifiers.length; i++) {
221
+ publicInputs[piIndex++] = nullifiers[i];
222
+ }
223
+ for (uint256 i = 0; i < extra.length; i++) {
224
+ publicInputs[piIndex++] = extra[i];
186
225
  }
187
- // Check the proof
188
- require(
189
- _verifier.verifyProof(
190
- proof.pA,
191
- proof.pB,
192
- proof.pC,
193
- fixedSizeInputs
194
- ),
195
- "Invalid proof"
196
- );
197
226
  }
227
+ _fillOutputsAndNonce(publicInputs, outputs, piIndex);
228
+ }
198
229
 
199
- // accept the transaction to consume the input UTXOs and produce new UTXOs
200
- uint256[] memory empty;
201
- processInputsAndOutputs(nullifiers, outputs, empty, address(0));
230
+ function _fillEcdhAndEncrypted(
231
+ uint256[] memory publicInputs,
232
+ uint256 piIndex
233
+ ) internal view returns (uint256) {
234
+ for (uint256 i = 0; i < ZetoAnonEncNullifierStorage.layout().dpe.ecdhPublicKey.length; ++i) {
235
+ publicInputs[piIndex++] = ZetoAnonEncNullifierStorage.layout().dpe.ecdhPublicKey[i];
236
+ }
237
+ for (uint256 i = 0; i < ZetoAnonEncNullifierStorage.layout().dpe.encryptedValues.length; ++i) {
238
+ publicInputs[piIndex++] = ZetoAnonEncNullifierStorage.layout().dpe.encryptedValues[i];
239
+ }
240
+ return piIndex;
241
+ }
202
242
 
203
- uint256[] memory encryptedValuesArray = new uint256[](
204
- encryptedValues.length
205
- );
206
- for (uint256 i = 0; i < encryptedValues.length; ++i) {
207
- encryptedValuesArray[i] = encryptedValues[i];
243
+ function _fillNullifiersAndRoot(
244
+ uint256[] memory publicInputs,
245
+ uint256[] memory nullifiers,
246
+ uint256 piIndex
247
+ ) internal view returns (uint256) {
248
+ for (uint256 i = 0; i < nullifiers.length; i++) {
249
+ publicInputs[piIndex++] = nullifiers[i];
208
250
  }
251
+ publicInputs[piIndex++] = ZetoAnonEncNullifierStorage.layout().dpe.root;
252
+ return piIndex;
253
+ }
209
254
 
210
- emit UTXOTransferWithEncryptedValues(
211
- nullifiers,
212
- outputs,
213
- encryptionNonce,
214
- ecdhPublicKey,
215
- encryptedValuesArray,
216
- msg.sender,
217
- data
218
- );
219
- return true;
255
+ function _fillEnablesAndExtra(
256
+ uint256[] memory publicInputs,
257
+ uint256[] memory nullifiers,
258
+ uint256[] memory extra,
259
+ uint256 piIndex
260
+ ) internal pure returns (uint256) {
261
+ for (uint256 i = 0; i < nullifiers.length; i++) {
262
+ publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1;
263
+ }
264
+ for (uint256 i = 0; i < extra.length; i++) {
265
+ publicInputs[piIndex++] = extra[i];
266
+ }
267
+ return piIndex;
220
268
  }
221
269
 
222
- function deposit(
223
- uint256 amount,
270
+ function _fillOutputsAndNonce(
271
+ uint256[] memory publicInputs,
224
272
  uint256[] memory outputs,
225
- Commonlib.Proof calldata proof,
226
- bytes calldata data
227
- ) public {
228
- _deposit(amount, outputs, proof);
229
- _mint(outputs, data);
273
+ uint256 piIndex
274
+ ) internal view {
275
+ for (uint256 i = 0; i < outputs.length; i++) {
276
+ publicInputs[piIndex++] = outputs[i];
277
+ }
278
+ publicInputs[piIndex++] = ZetoAnonEncNullifierStorage.layout().dpe.encryptionNonce;
230
279
  }
231
280
 
232
- function withdraw(
233
- uint256 amount,
234
- uint256[] memory nullifiers,
235
- uint256 output,
236
- uint256 root,
237
- Commonlib.Proof calldata proof,
238
- bytes calldata data
239
- ) public {
240
- uint256[] memory outputs = new uint256[](nullifiers.length);
241
- outputs[0] = output;
242
- // Check and pad commitments
243
- nullifiers = checkAndPadCommitments(nullifiers);
244
- outputs = checkAndPadCommitments(outputs);
245
- validateTransactionProposal(nullifiers, outputs, root, false);
281
+ function extraInputs()
282
+ internal
283
+ view
284
+ virtual
285
+ override
286
+ returns (uint256[] memory)
287
+ {
288
+ return new uint256[](0);
289
+ }
290
+ }
291
+
292
+ /// @dev ERC-7201 (`erc7201:zeto.storage.Zeto_AnonEncNullifier`).
293
+ library ZetoAnonEncNullifierStorage {
294
+ struct DecodedProofEncNullifier {
295
+ uint256 root;
296
+ uint256 encryptionNonce;
297
+ uint256[2] ecdhPublicKey;
298
+ uint256[] encryptedValues;
299
+ }
246
300
 
247
- _withdrawWithNullifiers(amount, nullifiers, output, root, proof);
248
- uint256[] memory empty;
249
- processInputsAndOutputs(nullifiers, outputs, empty, address(0));
250
- emit UTXOWithdraw(amount, nullifiers, output, msg.sender, data);
301
+ struct Layout {
302
+ DecodedProofEncNullifier dpe;
251
303
  }
252
304
 
253
- function mint(
254
- uint256[] memory utxos,
255
- bytes calldata data
256
- ) public onlyOwner {
257
- _mint(utxos, data);
305
+ bytes32 private constant STORAGE_LOCATION =
306
+ 0x36fc6ea34fa875375a7d6586407c2399b00c74acd3ef1f71bd14e60259234b00;
307
+
308
+ function layout() internal pure returns (Layout storage $) {
309
+ assembly {
310
+ $.slot := STORAGE_LOCATION
311
+ }
258
312
  }
259
313
  }