@lfdecentralizedtrust/zeto-contracts 0.2.1 → 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 (155) hide show
  1. package/README.md +70 -162
  2. package/contracts/factory.sol +30 -34
  3. package/contracts/factory_upgradeable.sol +160 -0
  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 +77 -27
  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 +8 -3
  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 +218 -360
  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 +9 -6
  104. package/ignition/modules/zeto_anon_burnable.ts +8 -7
  105. package/ignition/modules/zeto_anon_enc_nullifier.ts +33 -1
  106. package/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +2 -2
  107. package/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts +2 -1
  108. package/ignition/modules/zeto_anon_nullifier.ts +30 -5
  109. package/ignition/modules/zeto_anon_nullifier_burnable.ts +52 -17
  110. package/ignition/modules/zeto_anon_nullifier_kyc.ts +27 -12
  111. package/ignition/modules/zeto_anon_nullifier_qurrency.ts +2 -1
  112. package/ignition/modules/zeto_nf_anon_nullifier.ts +16 -12
  113. package/package.json +4 -2
  114. package/scripts/deploy_cloneable.ts +19 -10
  115. package/scripts/deploy_upgradeable.ts +9 -5
  116. package/scripts/tokens/Zeto_Anon.ts +3 -3
  117. package/scripts/tokens/Zeto_AnonBurnable.ts +1 -1
  118. package/scripts/tokens/Zeto_AnonEnc.ts +12 -3
  119. package/scripts/tokens/Zeto_AnonEncNullifier.ts +7 -3
  120. package/scripts/tokens/Zeto_AnonEncNullifierKyc.ts +1 -1
  121. package/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts +3 -1
  122. package/scripts/tokens/Zeto_AnonNullifier.ts +3 -1
  123. package/scripts/tokens/Zeto_AnonNullifierBurnable.ts +3 -1
  124. package/scripts/tokens/Zeto_AnonNullifierKyc.ts +1 -1
  125. package/scripts/tokens/Zeto_AnonNullifierQurrency.ts +3 -1
  126. package/scripts/tokens/Zeto_NfAnon.ts +2 -2
  127. package/scripts/tokens/Zeto_NfAnonNullifier.ts +3 -2
  128. package/test/factory.ts +46 -73
  129. package/test/factory_upgradeable.ts +311 -0
  130. package/test/lib/anon_nullifier_helpers.ts +89 -0
  131. package/test/lib/anon_zeto_helpers.ts +76 -0
  132. package/test/lib/deploy.ts +3 -2
  133. package/test/lib/utils.ts +74 -35
  134. package/test/test/escrow1.ts +185 -58
  135. package/test/test/escrow2.ts +200 -107
  136. package/test/test/qurrency.ts +13 -33
  137. package/test/usdc-shielding.ts +39 -26
  138. package/test/utils.ts +144 -21
  139. package/test/zeto_anon.ts +956 -465
  140. package/test/zeto_anon_enc.ts +881 -142
  141. package/test/zeto_anon_enc_nullifier.ts +847 -38
  142. package/test/zeto_anon_enc_nullifier_kyc.ts +120 -181
  143. package/test/zeto_anon_enc_nullifier_non_repudiation.ts +77 -46
  144. package/test/zeto_anon_nullifier.ts +1212 -953
  145. package/test/zeto_anon_nullifier_kyc.ts +674 -655
  146. package/test/zeto_anon_nullifier_qurrency.ts +452 -306
  147. package/test/zeto_nf_anon.ts +737 -137
  148. package/test/zeto_nf_anon_nullifier.ts +876 -246
  149. package/contracts/lib/zeto_base.sol +0 -293
  150. package/contracts/lib/zeto_fungible_withdraw.sol +0 -132
  151. package/contracts/lib/zeto_fungible_withdraw_nullifier.sol +0 -144
  152. package/contracts/lib/zeto_nullifier.sol +0 -334
  153. package/contracts/zkDvP.sol_ +0 -273
  154. package/test/zkDvP.ts_ +0 -455
  155. /package/contracts/lib/{common.sol → common/common.sol} +0 -0
@@ -20,7 +20,7 @@ import zetoModule from "../../ignition/modules/zeto_nf_anon_nullifier";
20
20
  export async function deployDependencies() {
21
21
  const [deployer] = await ethers.getSigners();
22
22
 
23
- const { verifier, lockVerifier, smtLib, poseidon3 } =
23
+ const { verifier, lockVerifier, smtLib, poseidon2, poseidon3 } =
24
24
  await ignition.deploy(zetoModule);
25
25
  return {
26
26
  deployer,
@@ -38,10 +38,11 @@ export async function deployDependencies() {
38
38
  batchLockVerifier: "0x0000000000000000000000000000000000000000",
39
39
  burnVerifier: "0x0000000000000000000000000000000000000000",
40
40
  batchBurnVerifier: "0x0000000000000000000000000000000000000000",
41
- }
41
+ },
42
42
  ],
43
43
  libraries: {
44
44
  SmtLib: smtLib.target,
45
+ PoseidonUnit2L: poseidon2.target,
45
46
  PoseidonUnit3L: poseidon3.target,
46
47
  },
47
48
  };
package/test/factory.ts CHANGED
@@ -47,7 +47,7 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
47
47
  batchLockVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
48
48
  burnVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
49
49
  batchBurnVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
50
- }
50
+ },
51
51
  };
52
52
  await expect(
53
53
  factory.connect(nonOwner).registerImplementation("test", implInfo as any),
@@ -73,7 +73,7 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
73
73
  batchLockVerifier: "0x0000000000000000000000000000000000000000",
74
74
  burnVerifier: "0x0000000000000000000000000000000000000000",
75
75
  batchBurnVerifier: "0x0000000000000000000000000000000000000000",
76
- }
76
+ },
77
77
  };
78
78
  await expect(
79
79
  factory.connect(deployer).registerImplementation("test", implInfo as any),
@@ -99,7 +99,7 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
99
99
  batchLockVerifier: "0x0000000000000000000000000000000000000000",
100
100
  burnVerifier: "0x0000000000000000000000000000000000000000",
101
101
  batchBurnVerifier: "0x0000000000000000000000000000000000000000",
102
- }
102
+ },
103
103
  };
104
104
  await expect(
105
105
  factory.connect(deployer).registerImplementation("test", implInfo as any),
@@ -125,7 +125,7 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
125
125
  batchLockVerifier: "0x0000000000000000000000000000000000000000",
126
126
  burnVerifier: "0x0000000000000000000000000000000000000000",
127
127
  batchBurnVerifier: "0x0000000000000000000000000000000000000000",
128
- }
128
+ },
129
129
  };
130
130
  await expect(
131
131
  factory.connect(deployer).registerImplementation("test", implInfo as any),
@@ -151,7 +151,7 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
151
151
  batchLockVerifier: "0x0000000000000000000000000000000000000000",
152
152
  burnVerifier: "0x0000000000000000000000000000000000000000",
153
153
  batchBurnVerifier: "0x0000000000000000000000000000000000000000",
154
- }
154
+ },
155
155
  };
156
156
  const tx1 = await factory
157
157
  .connect(deployer)
@@ -161,7 +161,12 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
161
161
  await expect(
162
162
  factory
163
163
  .connect(deployer)
164
- .deployZetoFungibleToken("name", "symbol", "test", await deployer.getAddress()),
164
+ .deployZetoFungibleToken(
165
+ "name",
166
+ "symbol",
167
+ "test",
168
+ await deployer.getAddress(),
169
+ ),
165
170
  ).rejectedWith("Factory: depositVerifier address is required");
166
171
  });
167
172
  it("attempting to deploy a fungible token but with a registered implementation that misses required depositVerifier should fail", async function () {
@@ -183,7 +188,7 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
183
188
  batchLockVerifier: "0x0000000000000000000000000000000000000000",
184
189
  burnVerifier: "0x0000000000000000000000000000000000000000",
185
190
  batchBurnVerifier: "0x0000000000000000000000000000000000000000",
186
- }
191
+ },
187
192
  };
188
193
  const tx1 = await factory
189
194
  .connect(deployer)
@@ -193,7 +198,12 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
193
198
  await expect(
194
199
  factory
195
200
  .connect(deployer)
196
- .deployZetoFungibleToken("name", "symbol", "test", await deployer.getAddress()),
201
+ .deployZetoFungibleToken(
202
+ "name",
203
+ "symbol",
204
+ "test",
205
+ await deployer.getAddress(),
206
+ ),
197
207
  ).rejectedWith("Factory: depositVerifier address is required");
198
208
  });
199
209
 
@@ -216,7 +226,7 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
216
226
  batchLockVerifier: "0x0000000000000000000000000000000000000000",
217
227
  burnVerifier: "0x0000000000000000000000000000000000000000",
218
228
  batchBurnVerifier: "0x0000000000000000000000000000000000000000",
219
- }
229
+ },
220
230
  };
221
231
  const tx1 = await factory
222
232
  .connect(deployer)
@@ -226,7 +236,12 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
226
236
  await expect(
227
237
  factory
228
238
  .connect(deployer)
229
- .deployZetoFungibleToken("name", "symbol", "test", await deployer.getAddress()),
239
+ .deployZetoFungibleToken(
240
+ "name",
241
+ "symbol",
242
+ "test",
243
+ await deployer.getAddress(),
244
+ ),
230
245
  ).rejectedWith("Factory: withdrawVerifier address is required");
231
246
  });
232
247
 
@@ -249,7 +264,7 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
249
264
  batchLockVerifier: "0x0000000000000000000000000000000000000000",
250
265
  burnVerifier: "0x0000000000000000000000000000000000000000",
251
266
  batchBurnVerifier: "0x0000000000000000000000000000000000000000",
252
- }
267
+ },
253
268
  };
254
269
  const tx1 = await factory
255
270
  .connect(deployer)
@@ -259,68 +274,15 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
259
274
  await expect(
260
275
  factory
261
276
  .connect(deployer)
262
- .deployZetoFungibleToken("name", "symbol", "test", await deployer.getAddress()),
277
+ .deployZetoFungibleToken(
278
+ "name",
279
+ "symbol",
280
+ "test",
281
+ await deployer.getAddress(),
282
+ ),
263
283
  ).rejectedWith("Factory: batchWithdrawVerifier address is required");
264
284
  });
265
285
 
266
- // it("attempting to deploy a fungible token but with a registered implementation that misses required lockVerifier should fail", async function () {
267
- // // we want to test the effectiveness of the factory contract
268
- // // to create clones of the Zeto implementation contract
269
- // const Factory = await ethers.getContractFactory("ZetoTokenFactory");
270
- // const factory = await Factory.deploy();
271
- // await factory.waitForDeployment();
272
-
273
- // const implInfo = {
274
- // implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
275
- // verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
276
- // batchVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
277
- // depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
278
- // withdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
279
- // batchWithdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
280
- // lockVerifier: "0x0000000000000000000000000000000000000000",
281
- // batchLockVerifier: "0x0000000000000000000000000000000000000000",
282
- // };
283
- // const tx1 = await factory
284
- // .connect(deployer)
285
- // .registerImplementation("test", implInfo as any);
286
- // await tx1.wait();
287
-
288
- // await expect(
289
- // factory
290
- // .connect(deployer)
291
- // .deployZetoFungibleToken("test", await deployer.getAddress()),
292
- // ).rejectedWith("Factory: lockVerifier address is required");
293
- // });
294
-
295
- // it("attempting to deploy a fungible token but with a registered implementation that misses required batchLockVerifier should fail", async function () {
296
- // // we want to test the effectiveness of the factory contract
297
- // // to create clones of the Zeto implementation contract
298
- // const Factory = await ethers.getContractFactory("ZetoTokenFactory");
299
- // const factory = await Factory.deploy();
300
- // await factory.waitForDeployment();
301
-
302
- // const implInfo = {
303
- // implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
304
- // verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
305
- // batchVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
306
- // depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
307
- // withdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
308
- // batchWithdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
309
- // lockVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
310
- // batchLockVerifier: "0x0000000000000000000000000000000000000000",
311
- // };
312
- // const tx1 = await factory
313
- // .connect(deployer)
314
- // .registerImplementation("test", implInfo as any);
315
- // await tx1.wait();
316
-
317
- // await expect(
318
- // factory
319
- // .connect(deployer)
320
- // .deployZetoFungibleToken("test", await deployer.getAddress()),
321
- // ).rejectedWith("Factory: batchLockVerifier address is required");
322
- // });
323
-
324
286
  it("attempting to deploy a fungible token with a properly registered implementation should succeed", async function () {
325
287
  // we want to test the effectiveness of the factory contract
326
288
  // to create clones of the Zeto implementation contract
@@ -328,8 +290,14 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
328
290
  const factory = await Factory.deploy();
329
291
  await factory.waitForDeployment();
330
292
 
293
+ // deploy a real Zeto token so that the "implementation" contract can
294
+ // pass the code length check in the ERC1967Proxy contract
295
+ const Zeto = await ethers.getContractFactory("Zeto_Anon");
296
+ const zeto = await Zeto.deploy();
297
+ await zeto.waitForDeployment();
298
+
331
299
  const implInfo = {
332
- implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
300
+ implementation: zeto.target,
333
301
  verifiers: {
334
302
  verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
335
303
  batchVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
@@ -340,7 +308,7 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
340
308
  batchLockVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
341
309
  burnVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
342
310
  batchBurnVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
343
- }
311
+ },
344
312
  };
345
313
  const tx1 = await factory
346
314
  .connect(deployer)
@@ -350,7 +318,12 @@ describe("(factory) Zeto based fungible token with anonymity without encryption
350
318
  await expect(
351
319
  factory
352
320
  .connect(deployer)
353
- .deployZetoFungibleToken("name", "symbol", "test", await deployer.getAddress()),
321
+ .deployZetoFungibleToken(
322
+ "name",
323
+ "symbol",
324
+ "test",
325
+ await deployer.getAddress(),
326
+ ),
354
327
  ).fulfilled;
355
328
  });
356
329
  });
@@ -0,0 +1,311 @@
1
+ // Copyright © 2026 Kaleido, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 (the "License");
6
+ // you may not use this file except in compliance with the License.
7
+ // You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing, software
12
+ // distributed under the License is distributed on an "AS IS" BASIS,
13
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ // See the License for the specific language governing permissions and
15
+ // limitations under the License.
16
+
17
+ import { ethers, network, upgrades } from "hardhat";
18
+ import { Signer } from "ethers";
19
+ import { expect } from "chai";
20
+
21
+ describe("(factory upgradeable) Zeto based fungible token with anonymity without encryption or nullifier", function () {
22
+ let deployer: Signer;
23
+ let nonOwner: Signer;
24
+
25
+ before(async function () {
26
+ if (network.name !== "hardhat") {
27
+ // accommodate for longer block times on public networks
28
+ this.timeout(120000);
29
+ }
30
+ [deployer, nonOwner] = await ethers.getSigners();
31
+ });
32
+
33
+ async function deployFactory() {
34
+ const Factory = await ethers.getContractFactory(
35
+ "ZetoTokenFactoryUpgradeable",
36
+ );
37
+ const proxy = await upgrades.deployProxy(Factory, [], {
38
+ kind: "uups",
39
+ initializer: "initialize",
40
+ });
41
+ await proxy.waitForDeployment();
42
+ return await ethers.getContractAt(
43
+ "ZetoTokenFactoryUpgradeable",
44
+ await proxy.getAddress(),
45
+ );
46
+ }
47
+
48
+ it("attempting to register an implementation as a non-owner should fail", async function () {
49
+ const factory = await deployFactory();
50
+
51
+ const implInfo = {
52
+ implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
53
+ verifiers: {
54
+ verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
55
+ batchVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
56
+ depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
57
+ withdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
58
+ batchWithdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
59
+ lockVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
60
+ batchLockVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
61
+ burnVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
62
+ batchBurnVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
63
+ },
64
+ };
65
+ await expect(
66
+ factory.connect(nonOwner).registerImplementation("test", implInfo as any),
67
+ ).rejectedWith(`reverted with custom error 'OwnableUnauthorizedAccount(`);
68
+ });
69
+
70
+ it("attempting to initialize twice should fail", async function () {
71
+ const factory = await deployFactory();
72
+
73
+ await expect(factory.initialize()).rejectedWith("InvalidInitialization");
74
+ });
75
+
76
+ it("attempting to register an implementation without the required implementation value should fail", async function () {
77
+ const factory = await deployFactory();
78
+
79
+ const implInfo = {
80
+ implementation: "0x0000000000000000000000000000000000000000",
81
+ verifiers: {
82
+ verifier: "0x0000000000000000000000000000000000000000",
83
+ batchVerifier: "0x0000000000000000000000000000000000000000",
84
+ depositVerifier: "0x0000000000000000000000000000000000000000",
85
+ withdrawVerifier: "0x0000000000000000000000000000000000000000",
86
+ batchWithdrawVerifier: "0x0000000000000000000000000000000000000000",
87
+ lockVerifier: "0x0000000000000000000000000000000000000000",
88
+ batchLockVerifier: "0x0000000000000000000000000000000000000000",
89
+ burnVerifier: "0x0000000000000000000000000000000000000000",
90
+ batchBurnVerifier: "0x0000000000000000000000000000000000000000",
91
+ },
92
+ };
93
+ await expect(
94
+ factory.connect(deployer).registerImplementation("test", implInfo as any),
95
+ ).rejectedWith("Factory: implementation address is required");
96
+ });
97
+
98
+ it("attempting to register an implementation without the required verifier value should fail", async function () {
99
+ const factory = await deployFactory();
100
+
101
+ const implInfo = {
102
+ implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
103
+ verifiers: {
104
+ verifier: "0x0000000000000000000000000000000000000000",
105
+ batchVerifier: "0x0000000000000000000000000000000000000000",
106
+ depositVerifier: "0x0000000000000000000000000000000000000000",
107
+ withdrawVerifier: "0x0000000000000000000000000000000000000000",
108
+ batchWithdrawVerifier: "0x0000000000000000000000000000000000000000",
109
+ lockVerifier: "0x0000000000000000000000000000000000000000",
110
+ batchLockVerifier: "0x0000000000000000000000000000000000000000",
111
+ burnVerifier: "0x0000000000000000000000000000000000000000",
112
+ batchBurnVerifier: "0x0000000000000000000000000000000000000000",
113
+ },
114
+ };
115
+ await expect(
116
+ factory.connect(deployer).registerImplementation("test", implInfo as any),
117
+ ).rejectedWith("Factory: verifier address is required");
118
+ });
119
+
120
+ it("attempting to register an implementation with the required values should succeed", async function () {
121
+ const factory = await deployFactory();
122
+
123
+ const implInfo = {
124
+ implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
125
+ verifiers: {
126
+ verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
127
+ batchVerifier: "0x0000000000000000000000000000000000000000",
128
+ depositVerifier: "0x0000000000000000000000000000000000000000",
129
+ withdrawVerifier: "0x0000000000000000000000000000000000000000",
130
+ batchWithdrawVerifier: "0x0000000000000000000000000000000000000000",
131
+ lockVerifier: "0x0000000000000000000000000000000000000000",
132
+ batchLockVerifier: "0x0000000000000000000000000000000000000000",
133
+ burnVerifier: "0x0000000000000000000000000000000000000000",
134
+ batchBurnVerifier: "0x0000000000000000000000000000000000000000",
135
+ },
136
+ };
137
+ await expect(
138
+ factory.connect(deployer).registerImplementation("test", implInfo as any),
139
+ ).fulfilled;
140
+ });
141
+
142
+ it("attempting to deploy a fungible token but with a registered implementation that misses required batchVerifier should fail", async function () {
143
+ const factory = await deployFactory();
144
+
145
+ const implInfo = {
146
+ implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
147
+ verifiers: {
148
+ verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
149
+ batchVerifier: "0x0000000000000000000000000000000000000000",
150
+ depositVerifier: "0x0000000000000000000000000000000000000000",
151
+ withdrawVerifier: "0x0000000000000000000000000000000000000000",
152
+ batchWithdrawVerifier: "0x0000000000000000000000000000000000000000",
153
+ lockVerifier: "0x0000000000000000000000000000000000000000",
154
+ batchLockVerifier: "0x0000000000000000000000000000000000000000",
155
+ burnVerifier: "0x0000000000000000000000000000000000000000",
156
+ batchBurnVerifier: "0x0000000000000000000000000000000000000000",
157
+ },
158
+ };
159
+ const tx1 = await factory
160
+ .connect(deployer)
161
+ .registerImplementation("test", implInfo as any);
162
+ await tx1.wait();
163
+
164
+ await expect(
165
+ factory
166
+ .connect(deployer)
167
+ .deployZetoFungibleToken(
168
+ "name",
169
+ "symbol",
170
+ "test",
171
+ await deployer.getAddress(),
172
+ ),
173
+ ).rejectedWith("Factory: depositVerifier address is required");
174
+ });
175
+
176
+ it("attempting to deploy a fungible token but with a registered implementation that misses required depositVerifier should fail", async function () {
177
+ const factory = await deployFactory();
178
+
179
+ const implInfo = {
180
+ implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
181
+ verifiers: {
182
+ verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
183
+ batchVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
184
+ depositVerifier: "0x0000000000000000000000000000000000000000",
185
+ withdrawVerifier: "0x0000000000000000000000000000000000000000",
186
+ batchWithdrawVerifier: "0x0000000000000000000000000000000000000000",
187
+ lockVerifier: "0x0000000000000000000000000000000000000000",
188
+ batchLockVerifier: "0x0000000000000000000000000000000000000000",
189
+ burnVerifier: "0x0000000000000000000000000000000000000000",
190
+ batchBurnVerifier: "0x0000000000000000000000000000000000000000",
191
+ },
192
+ };
193
+ const tx1 = await factory
194
+ .connect(deployer)
195
+ .registerImplementation("test", implInfo as any);
196
+ await tx1.wait();
197
+
198
+ await expect(
199
+ factory
200
+ .connect(deployer)
201
+ .deployZetoFungibleToken(
202
+ "name",
203
+ "symbol",
204
+ "test",
205
+ await deployer.getAddress(),
206
+ ),
207
+ ).rejectedWith("Factory: depositVerifier address is required");
208
+ });
209
+
210
+ it("attempting to deploy a fungible token but with a registered implementation that misses required withdrawVerifier should fail", async function () {
211
+ const factory = await deployFactory();
212
+
213
+ const implInfo = {
214
+ implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
215
+ verifiers: {
216
+ verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
217
+ batchVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
218
+ depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
219
+ withdrawVerifier: "0x0000000000000000000000000000000000000000",
220
+ batchWithdrawVerifier: "0x0000000000000000000000000000000000000000",
221
+ lockVerifier: "0x0000000000000000000000000000000000000000",
222
+ batchLockVerifier: "0x0000000000000000000000000000000000000000",
223
+ burnVerifier: "0x0000000000000000000000000000000000000000",
224
+ batchBurnVerifier: "0x0000000000000000000000000000000000000000",
225
+ },
226
+ };
227
+ const tx1 = await factory
228
+ .connect(deployer)
229
+ .registerImplementation("test", implInfo as any);
230
+ await tx1.wait();
231
+
232
+ await expect(
233
+ factory
234
+ .connect(deployer)
235
+ .deployZetoFungibleToken(
236
+ "name",
237
+ "symbol",
238
+ "test",
239
+ await deployer.getAddress(),
240
+ ),
241
+ ).rejectedWith("Factory: withdrawVerifier address is required");
242
+ });
243
+
244
+ it("attempting to deploy a fungible token but with a registered implementation that misses required batchWithdrawVerifier should fail", async function () {
245
+ const factory = await deployFactory();
246
+
247
+ const implInfo = {
248
+ implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
249
+ verifiers: {
250
+ verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
251
+ batchVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
252
+ depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
253
+ withdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
254
+ batchWithdrawVerifier: "0x0000000000000000000000000000000000000000",
255
+ lockVerifier: "0x0000000000000000000000000000000000000000",
256
+ batchLockVerifier: "0x0000000000000000000000000000000000000000",
257
+ burnVerifier: "0x0000000000000000000000000000000000000000",
258
+ batchBurnVerifier: "0x0000000000000000000000000000000000000000",
259
+ },
260
+ };
261
+ const tx1 = await factory
262
+ .connect(deployer)
263
+ .registerImplementation("test", implInfo as any);
264
+ await tx1.wait();
265
+
266
+ await expect(
267
+ factory
268
+ .connect(deployer)
269
+ .deployZetoFungibleToken(
270
+ "name",
271
+ "symbol",
272
+ "test",
273
+ await deployer.getAddress(),
274
+ ),
275
+ ).rejectedWith("Factory: batchWithdrawVerifier address is required");
276
+ });
277
+
278
+ it("attempting to deploy a fungible token with a properly registered implementation should succeed", async function () {
279
+ const factory = await deployFactory();
280
+
281
+ const implInfo = {
282
+ implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
283
+ verifiers: {
284
+ verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
285
+ batchVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
286
+ depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
287
+ withdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
288
+ batchWithdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
289
+ lockVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
290
+ batchLockVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
291
+ burnVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
292
+ batchBurnVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1",
293
+ },
294
+ };
295
+ const tx1 = await factory
296
+ .connect(deployer)
297
+ .registerImplementation("test", implInfo as any);
298
+ await tx1.wait();
299
+
300
+ await expect(
301
+ factory
302
+ .connect(deployer)
303
+ .deployZetoFungibleToken(
304
+ "name",
305
+ "symbol",
306
+ "test",
307
+ await deployer.getAddress(),
308
+ ),
309
+ ).fulfilled;
310
+ });
311
+ });
@@ -0,0 +1,89 @@
1
+ // Copyright © 2024 Kaleido, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ //
5
+ // ZK helpers for the `anon_nullifier_transfer` circuit family ({Zeto_AnonNullifier}
6
+ // unlocked-input transfers and createLock). Extracted so escrow and other suites
7
+ // can use them without importing the full `zeto_anon_nullifier.ts` Hardhat module.
8
+
9
+ import { AbiCoder, BigNumberish, ethers } from "ethers";
10
+ import { encodeProof } from "zeto-js";
11
+ import { groth16 } from "snarkjs";
12
+ import { User, UTXO, logger } from "./utils";
13
+
14
+ /**
15
+ * Build a Groth16 proof for an unlocked-input nullifier transfer (merkle-backed).
16
+ */
17
+ export async function prepareProof(
18
+ circuit: any,
19
+ provingKey: any,
20
+ signer: User,
21
+ inputs: UTXO[],
22
+ _nullifiers: UTXO[],
23
+ outputs: UTXO[],
24
+ root: BigInt,
25
+ merkleProof: BigInt[][],
26
+ owners: User[],
27
+ lockDelegate?: string,
28
+ ) {
29
+ const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [
30
+ BigNumberish,
31
+ BigNumberish,
32
+ ];
33
+ const inputCommitments: BigNumberish[] = inputs.map(
34
+ (input) => input.hash,
35
+ ) as BigNumberish[];
36
+ const inputValues = inputs.map((input) => BigInt(input.value || 0n));
37
+ const inputSalts = inputs.map((input) => input.salt || 0n);
38
+ const outputCommitments: BigNumberish[] = outputs.map(
39
+ (output) => output.hash,
40
+ ) as BigNumberish[];
41
+ const outputValues = outputs.map((output) => BigInt(output.value || 0n));
42
+ const outputOwnerPublicKeys: BigNumberish[][] = owners.map(
43
+ (owner) => owner.babyJubPublicKey,
44
+ ) as BigNumberish[][];
45
+
46
+ const startWitnessCalculation = Date.now();
47
+ const inputObj: Record<string, unknown> = {
48
+ nullifiers,
49
+ inputCommitments,
50
+ inputValues,
51
+ inputSalts,
52
+ inputOwnerPrivateKey: signer.formattedPrivateKey,
53
+ root,
54
+ enabled: nullifiers.map((n) => (n !== 0n ? 1 : 0)),
55
+ merkleProof,
56
+ outputCommitments,
57
+ outputValues,
58
+ outputSalts: outputs.map((output) => output.salt || 0n),
59
+ outputOwnerPublicKeys,
60
+ };
61
+ if (lockDelegate) {
62
+ inputObj["lockDelegate"] = ethers.toBigInt(lockDelegate);
63
+ }
64
+
65
+ const witness = await circuit.calculateWTNSBin(inputObj, true);
66
+ const timeWithnessCalculation = Date.now() - startWitnessCalculation;
67
+
68
+ const startProofGeneration = Date.now();
69
+ const { proof } = (await groth16.prove(provingKey, witness)) as {
70
+ proof: BigNumberish[];
71
+ publicSignals: BigNumberish[];
72
+ };
73
+ const timeProofGeneration = Date.now() - startProofGeneration;
74
+
75
+ logger.debug(
76
+ `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`,
77
+ );
78
+
79
+ const encodedProof = encodeProof(proof);
80
+ return encodedProof;
81
+ }
82
+
83
+ /** ABI encoding for nullifier transfer proofs: root prefix + Groth16 tuple. */
84
+ export function encodeToBytes(root: any, proof: any) {
85
+ return new AbiCoder().encode(
86
+ ["uint256 root", "tuple(uint256[2] pA, uint256[2][2] pB, uint256[2] pC)"],
87
+ [root, proof],
88
+ );
89
+ }