@lfdecentralizedtrust/zeto-contracts 0.2.2 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -162
- package/config/eip170.ts +30 -0
- package/contracts/factory.sol +30 -34
- package/contracts/factory_upgradeable.sol +11 -7
- package/contracts/lib/common/util.sol +40 -0
- package/contracts/lib/interfaces/ILockableCapability.sol +318 -0
- package/contracts/lib/interfaces/{izeto.sol → IZeto.sol} +13 -1
- package/contracts/lib/interfaces/{izeto_initializable.sol → IZetoInitializable.sol} +14 -12
- package/contracts/lib/interfaces/{izeto_kyc.sol → IZetoKyc.sol} +3 -3
- package/contracts/lib/interfaces/IZetoLockHooks.sol +42 -0
- package/contracts/lib/interfaces/IZetoLockableCapability.sol +237 -0
- package/contracts/lib/interfaces/IZetoStorage.sol +106 -0
- package/contracts/lib/interfaces/{izeto_lockable.sol → IZetoVerifier.sol} +8 -21
- package/contracts/lib/registry.sol +74 -26
- package/contracts/lib/storage/base.sol +210 -0
- package/contracts/lib/storage/nullifier.sol +166 -0
- package/contracts/lib/zeto_common.sol +277 -28
- package/contracts/lib/zeto_fungible.sol +443 -33
- package/contracts/lib/zeto_fungible_base.sol +69 -0
- package/contracts/lib/zeto_fungible_burn.sol +83 -53
- package/contracts/lib/zeto_fungible_burn_nullifier.sol +115 -72
- package/contracts/lib/zeto_fungible_nullifier.sol +167 -0
- package/contracts/lib/zeto_lockable.sol +219 -0
- package/contracts/lib/zeto_lockable_lib.sol +460 -0
- package/contracts/lib/zeto_lockable_storage.sol +43 -0
- package/contracts/lib/zeto_non_fungible.sol +228 -0
- package/contracts/lib/zeto_non_fungible_base.sol +61 -0
- package/contracts/lib/zeto_non_fungible_nullifier.sol +61 -0
- package/contracts/test/escrow1.sol +90 -34
- package/contracts/test/escrow2.sol +64 -29
- package/contracts/test/qurrency.sol +10 -2
- package/contracts/test/smt.sol +6 -1
- package/contracts/test/tendecimals.sol +14 -12
- package/contracts/verifiers/impl/anon.sol +189 -0
- package/contracts/verifiers/impl/anon_batch.sol +301 -0
- package/contracts/verifiers/impl/anon_enc.sol +266 -0
- package/contracts/verifiers/impl/anon_enc_batch.sol +602 -0
- package/contracts/verifiers/impl/anon_enc_nullifier.sol +287 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_batch.sol +679 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_kyc.sol +294 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_kyc_batch.sol +686 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_non_repudiation.sol +413 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_non_repudiation_batch.sol +1141 -0
- package/contracts/verifiers/impl/anon_nullifier_kyc_transfer.sol +217 -0
- package/contracts/verifiers/impl/anon_nullifier_kyc_transferLocked.sol +196 -0
- package/contracts/verifiers/impl/anon_nullifier_kyc_transferLocked_batch.sol +308 -0
- package/contracts/verifiers/impl/anon_nullifier_kyc_transfer_batch.sol +385 -0
- package/contracts/verifiers/impl/anon_nullifier_qurrency_transfer.sol +497 -0
- package/contracts/verifiers/impl/anon_nullifier_qurrency_transfer_batch.sol +1001 -0
- package/contracts/verifiers/{verifier_anon_nullifier_transferLocked.sol → impl/anon_nullifier_transfer.sol} +12 -19
- package/contracts/verifiers/{verifier_anon_nullifier_transferLocked_batch.sol → impl/anon_nullifier_transfer_batch.sol} +44 -51
- package/contracts/verifiers/impl/burn.sol +182 -0
- package/contracts/verifiers/impl/burn_batch.sol +238 -0
- package/contracts/verifiers/impl/burn_nullifier.sol +203 -0
- package/contracts/verifiers/impl/burn_nullifier_batch.sol +315 -0
- package/contracts/verifiers/impl/deposit.sol +182 -0
- package/contracts/verifiers/impl/deposit_kyc.sol +189 -0
- package/contracts/verifiers/impl/nf_anon.sol +175 -0
- package/contracts/verifiers/{verifier_nf_anon_nullifier_transferLocked.sol → impl/nf_anon_nullifier_transfer.sol} +6 -13
- package/contracts/verifiers/impl/withdraw.sol +189 -0
- package/contracts/verifiers/impl/withdraw_batch.sol +245 -0
- package/contracts/verifiers/impl/withdraw_nullifier.sol +210 -0
- package/contracts/verifiers/impl/withdraw_nullifier_batch.sol +322 -0
- package/contracts/verifiers/verifier_anon.sol +31 -186
- package/contracts/verifiers/verifier_anon_batch.sol +31 -298
- package/contracts/verifiers/verifier_anon_enc.sol +31 -263
- package/contracts/verifiers/verifier_anon_enc_batch.sol +31 -599
- package/contracts/verifiers/verifier_anon_enc_nullifier.sol +31 -284
- package/contracts/verifiers/verifier_anon_enc_nullifier_batch.sol +33 -676
- package/contracts/verifiers/verifier_anon_enc_nullifier_kyc.sol +31 -291
- package/contracts/verifiers/verifier_anon_enc_nullifier_kyc_batch.sol +33 -683
- package/contracts/verifiers/verifier_anon_enc_nullifier_non_repudiation.sol +33 -410
- package/contracts/verifiers/verifier_anon_enc_nullifier_non_repudiation_batch.sol +33 -1138
- package/contracts/verifiers/verifier_anon_nullifier_kyc_transfer.sol +33 -214
- package/contracts/verifiers/verifier_anon_nullifier_kyc_transferLocked.sol +33 -221
- package/contracts/verifiers/verifier_anon_nullifier_kyc_transferLocked_batch.sol +33 -389
- package/contracts/verifiers/verifier_anon_nullifier_kyc_transfer_batch.sol +33 -382
- package/contracts/verifiers/verifier_anon_nullifier_qurrency_transfer.sol +33 -221
- package/contracts/verifiers/verifier_anon_nullifier_qurrency_transfer_batch.sol +33 -389
- package/contracts/verifiers/verifier_anon_nullifier_transfer.sol +33 -207
- package/contracts/verifiers/verifier_anon_nullifier_transfer_batch.sol +33 -375
- package/contracts/verifiers/verifier_burn.sol +31 -179
- package/contracts/verifiers/verifier_burn_batch.sol +31 -235
- package/contracts/verifiers/verifier_burn_nullifier.sol +31 -200
- package/contracts/verifiers/verifier_burn_nullifier_batch.sol +31 -312
- package/contracts/verifiers/verifier_deposit.sol +31 -179
- package/contracts/verifiers/verifier_deposit_kyc.sol +34 -0
- package/contracts/verifiers/verifier_nf_anon.sol +31 -172
- package/contracts/verifiers/verifier_nf_anon_nullifier_transfer.sol +33 -179
- package/contracts/verifiers/verifier_withdraw.sol +31 -186
- package/contracts/verifiers/verifier_withdraw_batch.sol +31 -242
- package/contracts/verifiers/verifier_withdraw_nullifier.sol +31 -207
- package/contracts/verifiers/verifier_withdraw_nullifier_batch.sol +33 -319
- package/contracts/zeto_anon.sol +77 -231
- package/contracts/zeto_anon_burnable.sol +56 -12
- package/contracts/zeto_anon_enc.sol +93 -190
- package/contracts/zeto_anon_enc_nullifier.sol +249 -195
- package/contracts/zeto_anon_enc_nullifier_kyc.sol +51 -232
- package/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +231 -238
- package/contracts/zeto_anon_nullifier.sol +164 -298
- package/contracts/zeto_anon_nullifier_burnable.sol +68 -18
- package/contracts/zeto_anon_nullifier_kyc.sol +40 -345
- package/contracts/zeto_anon_nullifier_qurrency.sol +217 -361
- package/contracts/zeto_nf_anon.sol +55 -130
- package/contracts/zeto_nf_anon_nullifier.sol +90 -152
- package/hardhat.config.ts +18 -3
- package/ignition/modules/lib/deps.ts +13 -0
- package/ignition/modules/test/tendecimals.ts +7 -1
- package/ignition/modules/zeto_anon.ts +3 -0
- package/ignition/modules/zeto_anon_burnable.ts +11 -7
- package/ignition/modules/zeto_anon_enc.ts +3 -0
- package/ignition/modules/zeto_anon_enc_nullifier.ts +34 -0
- package/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +5 -2
- package/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts +3 -0
- package/ignition/modules/zeto_anon_nullifier.ts +31 -4
- package/ignition/modules/zeto_anon_nullifier_burnable.ts +53 -16
- package/ignition/modules/zeto_anon_nullifier_kyc.ts +30 -12
- package/ignition/modules/zeto_anon_nullifier_qurrency.ts +3 -0
- package/ignition/modules/zeto_nf_anon.ts +3 -1
- package/ignition/modules/zeto_nf_anon_nullifier.ts +17 -12
- package/package.json +7 -3
- package/scripts/deploy_cloneable.ts +19 -10
- package/scripts/deploy_upgradeable.ts +9 -5
- package/scripts/lib/zeto_libraries.ts +47 -0
- package/scripts/tokens/Zeto_Anon.ts +6 -3
- package/scripts/tokens/Zeto_AnonBurnable.ts +4 -1
- package/scripts/tokens/Zeto_AnonEnc.ts +15 -3
- package/scripts/tokens/Zeto_AnonEncNullifier.ts +11 -8
- package/scripts/tokens/Zeto_AnonEncNullifierKyc.ts +7 -6
- package/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts +7 -6
- package/scripts/tokens/Zeto_AnonNullifier.ts +7 -6
- package/scripts/tokens/Zeto_AnonNullifierBurnable.ts +7 -6
- package/scripts/tokens/Zeto_AnonNullifierKyc.ts +7 -6
- package/scripts/tokens/Zeto_AnonNullifierQurrency.ts +7 -8
- package/scripts/tokens/Zeto_NfAnon.ts +5 -3
- package/scripts/tokens/Zeto_NfAnonNullifier.ts +7 -7
- package/test/factory.ts +55 -73
- package/test/lib/anon_nullifier_helpers.ts +89 -0
- package/test/lib/anon_zeto_helpers.ts +76 -0
- package/test/lib/deploy.ts +5 -2
- package/test/lib/eip170.ts +23 -0
- package/test/lib/utils.ts +74 -35
- package/test/test/escrow1.ts +185 -58
- package/test/test/escrow2.ts +200 -107
- package/test/test/qurrency.ts +13 -33
- package/test/usdc-shielding.ts +39 -27
- package/test/utils.ts +144 -21
- package/test/zeto_anon.ts +956 -465
- package/test/zeto_anon_enc.ts +881 -143
- package/test/zeto_anon_enc_nullifier.ts +850 -39
- package/test/zeto_anon_enc_nullifier_kyc.ts +123 -182
- package/test/zeto_anon_enc_nullifier_non_repudiation.ts +80 -47
- package/test/zeto_anon_nullifier.ts +1212 -954
- package/test/zeto_anon_nullifier_kyc.ts +677 -656
- package/test/zeto_anon_nullifier_qurrency.ts +455 -307
- package/test/zeto_nf_anon.ts +737 -138
- package/test/zeto_nf_anon_nullifier.ts +876 -247
- package/contracts/lib/zeto_base.sol +0 -293
- package/contracts/lib/zeto_fungible_withdraw.sol +0 -132
- package/contracts/lib/zeto_fungible_withdraw_nullifier.sol +0 -144
- package/contracts/lib/zeto_nullifier.sol +0 -340
- package/contracts/zkDvP.sol_ +0 -273
- package/test/zkDvP.ts_ +0 -455
- /package/contracts/lib/{common.sol → common/common.sol} +0 -0
|
@@ -15,7 +15,12 @@
|
|
|
15
15
|
// limitations under the License.
|
|
16
16
|
|
|
17
17
|
import { ethers, network } from "hardhat";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
ContractTransactionReceipt,
|
|
20
|
+
Signer,
|
|
21
|
+
BigNumberish,
|
|
22
|
+
AbiCoder,
|
|
23
|
+
} from "ethers";
|
|
19
24
|
import { expect } from "chai";
|
|
20
25
|
import {
|
|
21
26
|
loadCircuit,
|
|
@@ -46,13 +51,17 @@ import {
|
|
|
46
51
|
} from "./lib/utils";
|
|
47
52
|
import {
|
|
48
53
|
loadProvingKeys,
|
|
49
|
-
|
|
54
|
+
prepareDepositKycProof,
|
|
50
55
|
prepareNullifierWithdrawProof,
|
|
56
|
+
encodeToBytesForDeposit,
|
|
57
|
+
encodeToBytesForWithdraw,
|
|
51
58
|
} from "./utils";
|
|
52
59
|
import { deployZeto } from "./lib/deploy";
|
|
53
60
|
const poseidonHash = Poseidon.poseidon4;
|
|
54
61
|
|
|
55
|
-
describe(
|
|
62
|
+
describe(
|
|
63
|
+
"Zeto based fungible token with anonymity using nullifiers and encryption with KYC",
|
|
64
|
+
function () {
|
|
56
65
|
let deployer: Signer;
|
|
57
66
|
let Alice: User;
|
|
58
67
|
let Bob: User;
|
|
@@ -91,11 +100,17 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
91
100
|
|
|
92
101
|
({ deployer, zeto, erc20 } = await deployZeto("Zeto_AnonEncNullifierKyc"));
|
|
93
102
|
|
|
94
|
-
const tx2 = await zeto
|
|
103
|
+
const tx2 = await zeto
|
|
104
|
+
.connect(deployer)
|
|
105
|
+
.register(Alice.babyJubPublicKey, "0x");
|
|
95
106
|
const result1 = await tx2.wait();
|
|
96
|
-
const tx3 = await zeto
|
|
107
|
+
const tx3 = await zeto
|
|
108
|
+
.connect(deployer)
|
|
109
|
+
.register(Bob.babyJubPublicKey, "0x");
|
|
97
110
|
const result2 = await tx3.wait();
|
|
98
|
-
const tx4 = await zeto
|
|
111
|
+
const tx4 = await zeto
|
|
112
|
+
.connect(deployer)
|
|
113
|
+
.register(Charlie.babyJubPublicKey, "0x");
|
|
99
114
|
const result3 = await tx4.wait();
|
|
100
115
|
|
|
101
116
|
const storage1 = new InMemoryDB(str2Bytes("alice"));
|
|
@@ -225,12 +240,13 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
225
240
|
|
|
226
241
|
const signerAddress = await Alice.signer.getAddress();
|
|
227
242
|
const events = parseUTXOEvents(zeto, result.txResult!);
|
|
228
|
-
|
|
229
|
-
expect(
|
|
243
|
+
const event = events[0];
|
|
244
|
+
expect(event.submitter).to.equal(signerAddress);
|
|
245
|
+
expect(event.inputs).to.deep.equal(nullifiers.map((n) => n.hash));
|
|
230
246
|
|
|
231
|
-
const incomingUTXOs: any =
|
|
247
|
+
const incomingUTXOs: any = event.outputs;
|
|
232
248
|
|
|
233
|
-
const ecdhPublicKey =
|
|
249
|
+
const ecdhPublicKey = event.ecdhPublicKey;
|
|
234
250
|
// check the non-empty output hashes are correct
|
|
235
251
|
for (let i = 0; i < outputUtxos.length; i++) {
|
|
236
252
|
const utxoOwner = outputOwners[i];
|
|
@@ -239,9 +255,9 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
239
255
|
ecdhPublicKey,
|
|
240
256
|
);
|
|
241
257
|
const plainText = poseidonDecrypt(
|
|
242
|
-
|
|
258
|
+
event.encryptedValues.slice(4 * i, 4 * i + 4),
|
|
243
259
|
sharedKey,
|
|
244
|
-
|
|
260
|
+
event.encryptionNonce,
|
|
245
261
|
2,
|
|
246
262
|
);
|
|
247
263
|
expect(plainText).to.deep.equal(
|
|
@@ -259,11 +275,6 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
259
275
|
await smtUnregistered.add(incomingUTXOs[i], incomingUTXOs[i]);
|
|
260
276
|
}
|
|
261
277
|
|
|
262
|
-
// check empty values, salt and hashes are empty
|
|
263
|
-
for (let i = outputUtxos.length; i < 10; i++) {
|
|
264
|
-
expect(incomingUTXOs[i]).to.equal(0);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
278
|
// mint sufficient balance in Zeto contract address for Alice to withdraw
|
|
268
279
|
const mintTx = await erc20.connect(deployer).mint(zeto, 3);
|
|
269
280
|
await mintTx.wait();
|
|
@@ -316,8 +327,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
316
327
|
3,
|
|
317
328
|
_withdrawNullifiers,
|
|
318
329
|
withdrawCommitments[0],
|
|
319
|
-
root.bigInt(),
|
|
320
|
-
withdrawEncodedProof,
|
|
330
|
+
encodeToBytesForWithdraw(root.bigInt(), withdrawEncodedProof),
|
|
321
331
|
"0x",
|
|
322
332
|
);
|
|
323
333
|
await tx.wait();
|
|
@@ -339,13 +349,29 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
339
349
|
|
|
340
350
|
utxo100 = newUTXO(100, Alice);
|
|
341
351
|
utxo0 = newUTXO(0, Alice);
|
|
342
|
-
const
|
|
352
|
+
const identitiesRoot = await smtKyc.root();
|
|
353
|
+
const proof3 = await smtKyc.generateCircomVerifierProof(
|
|
354
|
+
kycHash(Alice.babyJubPublicKey),
|
|
355
|
+
identitiesRoot,
|
|
356
|
+
);
|
|
357
|
+
const identitiesMerkleProofs = [
|
|
358
|
+
proof3.siblings.map((s) => s.bigInt()),
|
|
359
|
+
proof3.siblings.map((s) => s.bigInt()),
|
|
360
|
+
];
|
|
361
|
+
const { outputCommitments, encodedProof } = await prepareDepositKycProof(
|
|
343
362
|
Alice,
|
|
344
363
|
[utxo100, utxo0],
|
|
364
|
+
identitiesRoot.bigInt(),
|
|
365
|
+
identitiesMerkleProofs,
|
|
345
366
|
);
|
|
346
367
|
const tx2 = await zeto
|
|
347
368
|
.connect(Alice.signer)
|
|
348
|
-
.deposit(
|
|
369
|
+
.deposit(
|
|
370
|
+
100,
|
|
371
|
+
outputCommitments,
|
|
372
|
+
encodeToBytesForDeposit(encodedProof),
|
|
373
|
+
"0x",
|
|
374
|
+
);
|
|
349
375
|
await tx2.wait();
|
|
350
376
|
|
|
351
377
|
await smtAlice.add(utxo100.hash, utxo100.hash);
|
|
@@ -444,20 +470,21 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
444
470
|
// Bob parses the UTXOs from the onchain event
|
|
445
471
|
const signerAddress = await Alice.signer.getAddress();
|
|
446
472
|
const events = parseUTXOEvents(zeto, result2.txResult!);
|
|
447
|
-
|
|
448
|
-
expect(
|
|
449
|
-
expect(
|
|
450
|
-
|
|
451
|
-
await smtBob.add(
|
|
452
|
-
|
|
453
|
-
|
|
473
|
+
const event = events[0];
|
|
474
|
+
expect(event.submitter).to.equal(signerAddress);
|
|
475
|
+
expect(event.inputs).to.deep.equal([nullifier1.hash, nullifier2.hash]);
|
|
476
|
+
expect(event.outputs).to.deep.equal([_utxo3.hash, utxo4.hash]);
|
|
477
|
+
await smtBob.add(event.outputs[0], event.outputs[0]);
|
|
478
|
+
await smtBob.add(event.outputs[1], event.outputs[1]);
|
|
479
|
+
|
|
480
|
+
const ecdhPublicKey = event.ecdhPublicKey;
|
|
454
481
|
// Bob reconstructs the shared key using his private key and ephemeral public key
|
|
455
482
|
|
|
456
483
|
const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey);
|
|
457
484
|
const plainText = poseidonDecrypt(
|
|
458
|
-
|
|
485
|
+
event.encryptedValues.slice(0, 4),
|
|
459
486
|
sharedKey,
|
|
460
|
-
|
|
487
|
+
event.encryptionNonce,
|
|
461
488
|
2,
|
|
462
489
|
);
|
|
463
490
|
expect(plainText).to.deep.equal(result2.expectedPlainText.slice(0, 2));
|
|
@@ -522,8 +549,9 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
522
549
|
|
|
523
550
|
// Alice gets the new UTXOs from the onchain event and keeps the local SMT in sync
|
|
524
551
|
const events = parseUTXOEvents(zeto, result.txResult!);
|
|
525
|
-
|
|
526
|
-
await smtAlice.add(
|
|
552
|
+
const event = events[0];
|
|
553
|
+
await smtAlice.add(event.outputs[0], event.outputs[0]);
|
|
554
|
+
await smtAlice.add(event.outputs[1], event.outputs[1]);
|
|
527
555
|
}).timeout(600000);
|
|
528
556
|
|
|
529
557
|
it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () {
|
|
@@ -564,8 +592,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
564
592
|
80,
|
|
565
593
|
nullifiers,
|
|
566
594
|
outputCommitments[0],
|
|
567
|
-
root.bigInt(),
|
|
568
|
-
encodedProof,
|
|
595
|
+
encodeToBytesForWithdraw(root.bigInt(), encodedProof),
|
|
569
596
|
"0x",
|
|
570
597
|
);
|
|
571
598
|
await tx.wait();
|
|
@@ -583,8 +610,30 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
583
610
|
describe("unregistered user cases", function () {
|
|
584
611
|
let unregisteredUtxo100: UTXO;
|
|
585
612
|
let unregisteredUtxo0: UTXO;
|
|
613
|
+
let smtKycUnregistered: Merkletree;
|
|
614
|
+
|
|
615
|
+
before(async function () {
|
|
616
|
+
const storage5 = new InMemoryDB(str2Bytes("unregisteredKyc"));
|
|
617
|
+
smtKycUnregistered = new Merkletree(storage5, true, 10);
|
|
618
|
+
|
|
619
|
+
// add the unregistered user to the local KYC SMT, but not to the onchain SMT
|
|
620
|
+
await smtKycUnregistered.add(
|
|
621
|
+
kycHash(unregistered.babyJubPublicKey),
|
|
622
|
+
kycHash(unregistered.babyJubPublicKey),
|
|
623
|
+
);
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
it("deposit by an unregistered user should fail", async function () {
|
|
627
|
+
const identitiesRoot = await smtKycUnregistered.root();
|
|
628
|
+
const proof3 = await smtKycUnregistered.generateCircomVerifierProof(
|
|
629
|
+
kycHash(unregistered.babyJubPublicKey),
|
|
630
|
+
identitiesRoot,
|
|
631
|
+
);
|
|
632
|
+
const identitiesMerkleProofs = [
|
|
633
|
+
proof3.siblings.map((s) => s.bigInt()),
|
|
634
|
+
proof3.siblings.map((s) => s.bigInt()),
|
|
635
|
+
];
|
|
586
636
|
|
|
587
|
-
it("deposit by an unregistered user should succeed", async function () {
|
|
588
637
|
const tx = await erc20
|
|
589
638
|
.connect(deployer)
|
|
590
639
|
.mint(unregistered.ethAddress, 100);
|
|
@@ -596,150 +645,22 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
596
645
|
|
|
597
646
|
unregisteredUtxo100 = newUTXO(100, unregistered);
|
|
598
647
|
unregisteredUtxo0 = newUTXO(0, unregistered);
|
|
599
|
-
const { outputCommitments, encodedProof } = await
|
|
648
|
+
const { outputCommitments, encodedProof } = await prepareDepositKycProof(
|
|
600
649
|
unregistered,
|
|
601
650
|
[unregisteredUtxo100, unregisteredUtxo0],
|
|
651
|
+
identitiesRoot.bigInt(),
|
|
652
|
+
identitiesMerkleProofs,
|
|
602
653
|
);
|
|
603
|
-
const tx2 = await zeto
|
|
604
|
-
.connect(unregistered.signer)
|
|
605
|
-
.deposit(100, outputCommitments, encodedProof, "0x");
|
|
606
|
-
await tx2.wait();
|
|
607
|
-
|
|
608
|
-
// Alice tracks the UTXO inside the SMT
|
|
609
|
-
await smtAlice.add(unregisteredUtxo100.hash, unregisteredUtxo100.hash);
|
|
610
|
-
await smtAlice.add(unregisteredUtxo0.hash, unregisteredUtxo0.hash);
|
|
611
|
-
// Bob also locally tracks the UTXOs inside the SMT
|
|
612
|
-
await smtBob.add(unregisteredUtxo100.hash, unregisteredUtxo100.hash);
|
|
613
|
-
await smtBob.add(unregisteredUtxo0.hash, unregisteredUtxo0.hash);
|
|
614
|
-
});
|
|
615
|
-
|
|
616
|
-
it("transfer from an unregistered user should fail", async function () {
|
|
617
|
-
// catch up the local SMT for the unregistered user
|
|
618
|
-
await smtUnregistered.add(utxo100.hash, utxo100.hash);
|
|
619
|
-
await smtUnregistered.add(utxo0.hash, utxo0.hash);
|
|
620
|
-
await smtUnregistered.add(utxo1.hash, utxo1.hash);
|
|
621
|
-
await smtUnregistered.add(utxo2.hash, utxo2.hash);
|
|
622
|
-
await smtUnregistered.add(_utxo3.hash, _utxo3.hash);
|
|
623
|
-
await smtUnregistered.add(utxo4.hash, utxo4.hash);
|
|
624
|
-
await smtUnregistered.add(utxo6.hash, utxo6.hash);
|
|
625
|
-
await smtUnregistered.add(utxo7.hash, utxo7.hash);
|
|
626
|
-
await smtUnregistered.add(
|
|
627
|
-
withdrawChangeUTXO.hash,
|
|
628
|
-
withdrawChangeUTXO.hash,
|
|
629
|
-
);
|
|
630
|
-
await smtUnregistered.add(
|
|
631
|
-
unregisteredUtxo100.hash,
|
|
632
|
-
unregisteredUtxo100.hash,
|
|
633
|
-
);
|
|
634
|
-
await smtUnregistered.add(unregisteredUtxo0.hash, unregisteredUtxo0.hash);
|
|
635
|
-
const utxosRoot = await smtUnregistered.root();
|
|
636
|
-
|
|
637
|
-
const nullifier = newNullifier(unregisteredUtxo100, unregistered);
|
|
638
|
-
const output1 = newUTXO(100, Bob);
|
|
639
|
-
const output2 = newUTXO(0, unregistered);
|
|
640
|
-
const proof = await smtUnregistered.generateCircomVerifierProof(
|
|
641
|
-
unregisteredUtxo100.hash,
|
|
642
|
-
utxosRoot,
|
|
643
|
-
);
|
|
644
|
-
const merkleProofs = [
|
|
645
|
-
proof.siblings.map((s) => s.bigInt()),
|
|
646
|
-
proof.siblings.map((s) => s.bigInt()),
|
|
647
|
-
];
|
|
648
|
-
|
|
649
|
-
// add the unregistered user to the local KYC SMT, but not to the onchain SMT
|
|
650
|
-
await smtKyc.add(
|
|
651
|
-
kycHash(unregistered.babyJubPublicKey),
|
|
652
|
-
kycHash(unregistered.babyJubPublicKey),
|
|
653
|
-
);
|
|
654
|
-
const identitiesRoot = await smtKyc.root();
|
|
655
|
-
const proof3 = await smtKyc.generateCircomVerifierProof(
|
|
656
|
-
kycHash(unregistered.babyJubPublicKey),
|
|
657
|
-
identitiesRoot,
|
|
658
|
-
);
|
|
659
|
-
const proof4 = await smtKyc.generateCircomVerifierProof(
|
|
660
|
-
kycHash(Bob.babyJubPublicKey),
|
|
661
|
-
identitiesRoot,
|
|
662
|
-
);
|
|
663
|
-
const identitiesMerkleProofs = [
|
|
664
|
-
proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (unregistered)
|
|
665
|
-
proof4.siblings.map((s) => s.bigInt()), // identity proof for the 1st owner of the output UTXO (Bob)
|
|
666
|
-
proof3.siblings.map((s) => s.bigInt()), // identity proof for the 2nd owner of the output UTXO (unregistered)
|
|
667
|
-
];
|
|
668
654
|
await expect(
|
|
669
|
-
|
|
670
|
-
unregistered
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
[Bob, unregistered],
|
|
679
|
-
),
|
|
680
|
-
).rejectedWith("Invalid proof");
|
|
681
|
-
});
|
|
682
|
-
|
|
683
|
-
it("the unregistered user can still withdraw their UTXOs to ERC20 tokens", async function () {
|
|
684
|
-
const startingBalance = await erc20.balanceOf(unregistered.ethAddress);
|
|
685
|
-
// unregistered user generates the nullifiers for the UTXOs to be spent
|
|
686
|
-
const nullifier1 = newNullifier(unregisteredUtxo100, unregistered);
|
|
687
|
-
|
|
688
|
-
// unregistered user generates inclusion proofs for the UTXOs to be spent
|
|
689
|
-
let root = await smtUnregistered.root();
|
|
690
|
-
const proof1 = await smtUnregistered.generateCircomVerifierProof(
|
|
691
|
-
unregisteredUtxo100.hash,
|
|
692
|
-
root,
|
|
693
|
-
);
|
|
694
|
-
const proof2 = await smtUnregistered.generateCircomVerifierProof(
|
|
695
|
-
0n,
|
|
696
|
-
root,
|
|
697
|
-
);
|
|
698
|
-
const merkleProofs = [
|
|
699
|
-
proof1.siblings.map((s) => s.bigInt()),
|
|
700
|
-
proof2.siblings.map((s) => s.bigInt()),
|
|
701
|
-
];
|
|
702
|
-
|
|
703
|
-
// unregistered user proposes the output ERC20 tokens
|
|
704
|
-
const unregisteredWithdrawChangeUTXO = newUTXO(0, unregistered);
|
|
705
|
-
|
|
706
|
-
const { nullifiers, outputCommitments, encodedProof } =
|
|
707
|
-
await prepareNullifierWithdrawProof(
|
|
708
|
-
unregistered,
|
|
709
|
-
[unregisteredUtxo100, ZERO_UTXO],
|
|
710
|
-
[nullifier1, ZERO_UTXO],
|
|
711
|
-
unregisteredWithdrawChangeUTXO,
|
|
712
|
-
root.bigInt(),
|
|
713
|
-
merkleProofs,
|
|
714
|
-
);
|
|
715
|
-
|
|
716
|
-
// unregistered user withdraws her UTXOs to ERC20 tokens
|
|
717
|
-
const tx = await zeto
|
|
718
|
-
.connect(unregistered.signer)
|
|
719
|
-
.withdraw(
|
|
720
|
-
100,
|
|
721
|
-
nullifiers,
|
|
722
|
-
outputCommitments[0],
|
|
723
|
-
root.bigInt(),
|
|
724
|
-
encodedProof,
|
|
725
|
-
"0x",
|
|
726
|
-
);
|
|
727
|
-
await tx.wait();
|
|
728
|
-
|
|
729
|
-
// Alice tracks the UTXO inside the SMT
|
|
730
|
-
await smtAlice.add(
|
|
731
|
-
unregisteredWithdrawChangeUTXO.hash,
|
|
732
|
-
unregisteredWithdrawChangeUTXO.hash,
|
|
733
|
-
);
|
|
734
|
-
// Bob also locally tracks the UTXOs inside the SMT
|
|
735
|
-
await smtBob.add(
|
|
736
|
-
unregisteredWithdrawChangeUTXO.hash,
|
|
737
|
-
unregisteredWithdrawChangeUTXO.hash,
|
|
738
|
-
);
|
|
739
|
-
|
|
740
|
-
// unregistered user checks her ERC20 balance
|
|
741
|
-
const endingBalance = await erc20.balanceOf(unregistered.ethAddress);
|
|
742
|
-
expect(endingBalance - startingBalance).to.be.equal(100);
|
|
655
|
+
zeto
|
|
656
|
+
.connect(unregistered.signer)
|
|
657
|
+
.deposit(
|
|
658
|
+
100,
|
|
659
|
+
outputCommitments,
|
|
660
|
+
encodeToBytesForDeposit(encodedProof),
|
|
661
|
+
"0x",
|
|
662
|
+
),
|
|
663
|
+
).to.be.rejectedWith("VM Exception while processing transaction: reverted with custom error 'InvalidProof()'");
|
|
743
664
|
});
|
|
744
665
|
});
|
|
745
666
|
|
|
@@ -788,8 +709,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
788
709
|
10,
|
|
789
710
|
nullifiers,
|
|
790
711
|
outputCommitments[0],
|
|
791
|
-
root.bigInt(),
|
|
792
|
-
encodedProof,
|
|
712
|
+
encodeToBytesForWithdraw(root.bigInt(), encodedProof),
|
|
793
713
|
"0x",
|
|
794
714
|
),
|
|
795
715
|
).rejectedWith("UTXOAlreadySpent");
|
|
@@ -1181,11 +1101,13 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
1181
1101
|
const tx = await zeto.connect(signer.signer).transfer(
|
|
1182
1102
|
nullifiers.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works
|
|
1183
1103
|
outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1104
|
+
encodeToBytes(
|
|
1105
|
+
root,
|
|
1106
|
+
encryptionNonce,
|
|
1107
|
+
ecdhPublicKey,
|
|
1108
|
+
encryptedValues,
|
|
1109
|
+
encodedProof,
|
|
1110
|
+
),
|
|
1189
1111
|
"0x",
|
|
1190
1112
|
);
|
|
1191
1113
|
const results: ContractTransactionReceipt | null = await tx.wait();
|
|
@@ -1195,3 +1117,22 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
1195
1117
|
return results;
|
|
1196
1118
|
}
|
|
1197
1119
|
});
|
|
1120
|
+
|
|
1121
|
+
function encodeToBytes(
|
|
1122
|
+
root: any,
|
|
1123
|
+
encryptionNonce: any,
|
|
1124
|
+
ecdhPublicKey: any,
|
|
1125
|
+
encryptedValues: any,
|
|
1126
|
+
proof: any,
|
|
1127
|
+
) {
|
|
1128
|
+
return new AbiCoder().encode(
|
|
1129
|
+
[
|
|
1130
|
+
"uint256 root",
|
|
1131
|
+
"uint256 encryptionNonce",
|
|
1132
|
+
"uint256[2] ecdhPublicKey",
|
|
1133
|
+
"uint256[] encryptedValues",
|
|
1134
|
+
"tuple(uint256[2] pA, uint256[2][2] pB, uint256[2] pC)",
|
|
1135
|
+
],
|
|
1136
|
+
[root, encryptionNonce, ecdhPublicKey, encryptedValues, proof],
|
|
1137
|
+
);
|
|
1138
|
+
}
|
|
@@ -15,7 +15,12 @@
|
|
|
15
15
|
// limitations under the License.
|
|
16
16
|
|
|
17
17
|
import { ethers, network } from "hardhat";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
ContractTransactionReceipt,
|
|
20
|
+
Signer,
|
|
21
|
+
BigNumberish,
|
|
22
|
+
AbiCoder,
|
|
23
|
+
} from "ethers";
|
|
19
24
|
import { expect } from "chai";
|
|
20
25
|
import {
|
|
21
26
|
loadCircuit,
|
|
@@ -46,11 +51,15 @@ import {
|
|
|
46
51
|
loadProvingKeys,
|
|
47
52
|
prepareDepositProof,
|
|
48
53
|
prepareNullifierWithdrawProof,
|
|
54
|
+
encodeToBytesForDeposit,
|
|
55
|
+
encodeToBytesForWithdraw,
|
|
49
56
|
} from "./utils";
|
|
50
57
|
import { deployZeto } from "./lib/deploy";
|
|
51
58
|
const poseidonHash = Poseidon.poseidon4;
|
|
52
59
|
|
|
53
|
-
describe(
|
|
60
|
+
describe(
|
|
61
|
+
"Zeto based fungible token with anonymity using nullifiers and encryption for non-repudiation",
|
|
62
|
+
function () {
|
|
54
63
|
let deployer: Signer;
|
|
55
64
|
let Alice: User;
|
|
56
65
|
let Bob: User;
|
|
@@ -177,12 +186,13 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
177
186
|
|
|
178
187
|
const signerAddress = await Alice.signer.getAddress();
|
|
179
188
|
const events = parseUTXOEvents(zeto, result.txResult!);
|
|
180
|
-
|
|
181
|
-
expect(
|
|
189
|
+
const event = events[0];
|
|
190
|
+
expect(event.submitter).to.equal(signerAddress);
|
|
191
|
+
expect(event.inputs).to.deep.equal(nullifiers.map((n) => n.hash));
|
|
182
192
|
|
|
183
|
-
const incomingUTXOs: any =
|
|
193
|
+
const incomingUTXOs: any = event.outputs;
|
|
184
194
|
|
|
185
|
-
const ecdhPublicKey =
|
|
195
|
+
const ecdhPublicKey = event.ecdhPublicKey;
|
|
186
196
|
|
|
187
197
|
// check the non-empty output hashes are correct
|
|
188
198
|
for (let i = 0; i < outputUtxos.length; i++) {
|
|
@@ -192,9 +202,9 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
192
202
|
ecdhPublicKey,
|
|
193
203
|
);
|
|
194
204
|
const plainText = poseidonDecrypt(
|
|
195
|
-
|
|
205
|
+
event.encryptedValuesForReceiver.slice(4 * i, 4 * i + 4),
|
|
196
206
|
sharedKey,
|
|
197
|
-
|
|
207
|
+
event.encryptionNonce,
|
|
198
208
|
2,
|
|
199
209
|
);
|
|
200
210
|
expect(plainText).to.deep.equal(
|
|
@@ -210,20 +220,15 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
210
220
|
await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]);
|
|
211
221
|
await smtBob.add(incomingUTXOs[i], incomingUTXOs[i]);
|
|
212
222
|
}
|
|
213
|
-
|
|
214
|
-
// check empty values, salt and hashes are empty
|
|
215
|
-
for (let i = outputUtxos.length; i < 10; i++) {
|
|
216
|
-
expect(incomingUTXOs[i]).to.equal(0);
|
|
217
|
-
}
|
|
218
223
|
// The regulator uses the encrypted values in the event to decrypt and recover the UTXO value and salt
|
|
219
224
|
const auditKey = genEcdhSharedKey(
|
|
220
225
|
Authority.babyJubPrivateKey,
|
|
221
226
|
ecdhPublicKey,
|
|
222
227
|
);
|
|
223
228
|
const auditPlainText = poseidonDecrypt(
|
|
224
|
-
|
|
229
|
+
event.encryptedValuesForAuthority,
|
|
225
230
|
auditKey,
|
|
226
|
-
|
|
231
|
+
event.encryptionNonce,
|
|
227
232
|
62,
|
|
228
233
|
);
|
|
229
234
|
|
|
@@ -252,12 +257,6 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
252
257
|
expect(calHash).to.equal(outputUtxos[i].hash);
|
|
253
258
|
}
|
|
254
259
|
|
|
255
|
-
// check empty hashes are empty
|
|
256
|
-
for (let i = outputUtxos.length; i < 10; i++) {
|
|
257
|
-
expect(auditPlainText[2 * i + 42]).to.equal(0);
|
|
258
|
-
expect(auditPlainText[2 * i + 43]).to.equal(0);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
260
|
// mint sufficient balance in Zeto contract address for Alice to withdraw
|
|
262
261
|
const mintTx = await erc20.connect(deployer).mint(zeto, 3);
|
|
263
262
|
await mintTx.wait();
|
|
@@ -310,8 +309,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
310
309
|
3,
|
|
311
310
|
_withdrawNullifiers,
|
|
312
311
|
withdrawCommitments[0],
|
|
313
|
-
root.bigInt(),
|
|
314
|
-
withdrawEncodedProof,
|
|
312
|
+
encodeToBytesForWithdraw(root.bigInt(), withdrawEncodedProof),
|
|
315
313
|
"0x",
|
|
316
314
|
);
|
|
317
315
|
await tx.wait();
|
|
@@ -339,7 +337,12 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
339
337
|
);
|
|
340
338
|
const tx2 = await zeto
|
|
341
339
|
.connect(Alice.signer)
|
|
342
|
-
.deposit(
|
|
340
|
+
.deposit(
|
|
341
|
+
100,
|
|
342
|
+
outputCommitments,
|
|
343
|
+
encodeToBytesForDeposit(encodedProof),
|
|
344
|
+
"0x",
|
|
345
|
+
);
|
|
343
346
|
await tx2.wait();
|
|
344
347
|
|
|
345
348
|
await smtAlice.add(utxo100.hash, utxo100.hash);
|
|
@@ -414,20 +417,21 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
414
417
|
// Bob parses the UTXOs from the onchain event
|
|
415
418
|
const signerAddress = await Alice.signer.getAddress();
|
|
416
419
|
const events = parseUTXOEvents(zeto, result2.txResult!);
|
|
417
|
-
|
|
418
|
-
expect(
|
|
419
|
-
expect(
|
|
420
|
-
|
|
421
|
-
await smtBob.add(
|
|
422
|
-
|
|
423
|
-
|
|
420
|
+
const event = events[0];
|
|
421
|
+
expect(event.submitter).to.equal(signerAddress);
|
|
422
|
+
expect(event.inputs).to.deep.equal([nullifier1.hash, nullifier2.hash]);
|
|
423
|
+
expect(event.outputs).to.deep.equal([_utxo3.hash, utxo4.hash]);
|
|
424
|
+
await smtBob.add(event.outputs[0], event.outputs[0]);
|
|
425
|
+
await smtBob.add(event.outputs[1], event.outputs[1]);
|
|
426
|
+
|
|
427
|
+
const ecdhPublicKey = event.ecdhPublicKey;
|
|
424
428
|
// Bob reconstructs the shared key using his private key and ephemeral public key
|
|
425
429
|
|
|
426
430
|
const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey);
|
|
427
431
|
const plainText1 = poseidonDecrypt(
|
|
428
|
-
|
|
432
|
+
event.encryptedValuesForReceiver.slice(0, 4),
|
|
429
433
|
sharedKey,
|
|
430
|
-
|
|
434
|
+
event.encryptionNonce,
|
|
431
435
|
2,
|
|
432
436
|
);
|
|
433
437
|
expect(plainText1).to.deep.equal(result2.expectedPlainText.slice(0, 2));
|
|
@@ -441,9 +445,9 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
441
445
|
ecdhPublicKey,
|
|
442
446
|
);
|
|
443
447
|
const plainText2 = poseidonDecrypt(
|
|
444
|
-
|
|
448
|
+
event.encryptedValuesForAuthority,
|
|
445
449
|
sharedKey2,
|
|
446
|
-
|
|
450
|
+
event.encryptionNonce,
|
|
447
451
|
14,
|
|
448
452
|
);
|
|
449
453
|
expect(plainText2).to.deep.equal([
|
|
@@ -527,8 +531,9 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
527
531
|
|
|
528
532
|
// Alice gets the new UTXOs from the onchain event and keeps the local SMT in sync
|
|
529
533
|
const events = parseUTXOEvents(zeto, result.txResult!);
|
|
530
|
-
|
|
531
|
-
await smtAlice.add(
|
|
534
|
+
const event = events[0];
|
|
535
|
+
await smtAlice.add(event.outputs[0], event.outputs[0]);
|
|
536
|
+
await smtAlice.add(event.outputs[1], event.outputs[1]);
|
|
532
537
|
}).timeout(600000);
|
|
533
538
|
|
|
534
539
|
it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () {
|
|
@@ -568,8 +573,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
568
573
|
80,
|
|
569
574
|
nullifiers,
|
|
570
575
|
outputCommitments[0],
|
|
571
|
-
root.bigInt(),
|
|
572
|
-
encodedProof,
|
|
576
|
+
encodeToBytesForWithdraw(root.bigInt(), encodedProof),
|
|
573
577
|
"0x",
|
|
574
578
|
);
|
|
575
579
|
await tx.wait();
|
|
@@ -629,8 +633,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
629
633
|
80,
|
|
630
634
|
nullifiers,
|
|
631
635
|
outputCommitments[0],
|
|
632
|
-
root.bigInt(),
|
|
633
|
-
encodedProof,
|
|
636
|
+
encodeToBytesForWithdraw(root.bigInt(), encodedProof),
|
|
634
637
|
"0x",
|
|
635
638
|
),
|
|
636
639
|
).rejectedWith("UTXOAlreadySpent");
|
|
@@ -944,12 +947,14 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
944
947
|
const tx = await zeto.connect(signer.signer).transfer(
|
|
945
948
|
nullifiers.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works
|
|
946
949
|
outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
950
|
+
encodeToBytes(
|
|
951
|
+
root,
|
|
952
|
+
encryptionNonce,
|
|
953
|
+
ecdhPublicKey,
|
|
954
|
+
encryptedValuesForReceiver,
|
|
955
|
+
encryptedValuesForRegulator,
|
|
956
|
+
encodedProof,
|
|
957
|
+
),
|
|
953
958
|
"0x",
|
|
954
959
|
);
|
|
955
960
|
const results: ContractTransactionReceipt | null = await tx.wait();
|
|
@@ -959,3 +964,31 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
959
964
|
return results;
|
|
960
965
|
}
|
|
961
966
|
});
|
|
967
|
+
|
|
968
|
+
function encodeToBytes(
|
|
969
|
+
root: any,
|
|
970
|
+
encryptionNonce: any,
|
|
971
|
+
ecdhPublicKey: any,
|
|
972
|
+
encryptedValuesForReceiver: any,
|
|
973
|
+
encryptedValuesForAuthority: any,
|
|
974
|
+
proof: any,
|
|
975
|
+
) {
|
|
976
|
+
return new AbiCoder().encode(
|
|
977
|
+
[
|
|
978
|
+
"uint256 root",
|
|
979
|
+
"uint256 encryptionNonce",
|
|
980
|
+
"uint256[2] ecdhPublicKey",
|
|
981
|
+
"uint256[] encryptedValuesForReceiver",
|
|
982
|
+
"uint256[] encryptedValuesForAuthority",
|
|
983
|
+
"tuple(uint256[2] pA, uint256[2][2] pB, uint256[2] pC)",
|
|
984
|
+
],
|
|
985
|
+
[
|
|
986
|
+
root,
|
|
987
|
+
encryptionNonce,
|
|
988
|
+
ecdhPublicKey,
|
|
989
|
+
encryptedValuesForReceiver,
|
|
990
|
+
encryptedValuesForAuthority,
|
|
991
|
+
proof,
|
|
992
|
+
],
|
|
993
|
+
);
|
|
994
|
+
}
|