From 5ae387b41d527e776617e9cc42446e789031c1f5 Mon Sep 17 00:00:00 2001 From: Jim Zhang Date: Thu, 26 Sep 2024 11:58:31 -0400 Subject: [PATCH 1/3] Add delegate to lockProof() Signed-off-by: Jim Zhang --- solidity/contracts/lib/zeto_common.sol | 12 ++++++++++-- solidity/contracts/zkDvP.sol | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/solidity/contracts/lib/zeto_common.sol b/solidity/contracts/lib/zeto_common.sol index 567216e..83d271d 100644 --- a/solidity/contracts/lib/zeto_common.sol +++ b/solidity/contracts/lib/zeto_common.sol @@ -43,9 +43,17 @@ abstract contract ZetoCommon is OwnableUpgradeable { // should be called by escrow contracts that will use uploaded proofs // to execute transactions, in order to prevent the proof from being used // by parties other than the escrow contract - function lockProof(Commonlib.Proof calldata proof) public { + function lockProof( + Commonlib.Proof calldata proof, + address delegate + ) public { bytes32 proofHash = Commonlib.getProofHash(proof); - lockedProofs[proofHash] = msg.sender; + require(lockedProofs[proofHash] == address(0), "Proof already locked"); + if (delegate != address(0)) { + lockedProofs[proofHash] = delegate; + } else { + lockedProofs[proofHash] = msg.sender; + } } function sortInputsAndOutputs( diff --git a/solidity/contracts/zkDvP.sol b/solidity/contracts/zkDvP.sol index a36d2f9..87839c8 100644 --- a/solidity/contracts/zkDvP.sol +++ b/solidity/contracts/zkDvP.sol @@ -206,8 +206,10 @@ contract zkDvP { bytes32 proofHash = getProofHash(proof); if (trade.paymentProofHash == proofHash) { trade.paymentProof = proof; + paymentToken.lockProof(proof, address(this)); } else if (trade.assetProofHash == proofHash) { trade.assetProof = proof; + assetToken.lockProof(proof, address(this)); } else { revert("Invalid proof"); } From 07379c30bb6071a893c1d714e47f7f1a82fd3296 Mon Sep 17 00:00:00 2001 From: Jim Zhang Date: Thu, 26 Sep 2024 13:52:00 -0400 Subject: [PATCH 2/3] Allow proof lock to be updated Signed-off-by: Jim Zhang --- solidity/contracts/lib/zeto_common.sol | 6 +++++- solidity/test/zkDvP.ts | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/solidity/contracts/lib/zeto_common.sol b/solidity/contracts/lib/zeto_common.sol index 83d271d..0b2ea79 100644 --- a/solidity/contracts/lib/zeto_common.sol +++ b/solidity/contracts/lib/zeto_common.sol @@ -48,7 +48,11 @@ abstract contract ZetoCommon is OwnableUpgradeable { address delegate ) public { bytes32 proofHash = Commonlib.getProofHash(proof); - require(lockedProofs[proofHash] == address(0), "Proof already locked"); + require( + lockedProofs[proofHash] == address(0) || + lockedProofs[proofHash] == msg.sender, + "Proof already locked by another party" + ); if (delegate != address(0)) { lockedProofs[proofHash] = delegate; } else { diff --git a/solidity/test/zkDvP.ts b/solidity/test/zkDvP.ts index 9159fe4..4540473 100644 --- a/solidity/test/zkDvP.ts +++ b/solidity/test/zkDvP.ts @@ -219,6 +219,17 @@ describe("DvP flows between fungible and non-fungible tokens based on Zeto with await expect(zkDvP.connect(Bob.signer).acceptTrade(tradeId, [0, 0], [0, 0], mockProofHash, 0, 0, mockProofHash)).rejectedWith("Payment inputs must be provided to accept the trade"); await expect(zkDvP.connect(Bob.signer).acceptTrade(tradeId, [utxo3.hash, utxo4.hash], [0, 0], mockProofHash, 0, 0, mockProofHash)).rejectedWith("Payment outputs must be provided to accept the trade"); }); + + it("test proof locking", async function () { + const circuit1 = await loadCircuit('anon'); + const { provingKeyFile: provingKey1 } = loadProvingKeys('anon'); + const utxo1 = newUTXO(100, Alice); + const proof = await zetoAnonTests.prepareProof(circuit1, provingKey1, Alice, [utxo1, ZERO_UTXO], [utxo1, ZERO_UTXO], [Alice, {}]); + + await expect(zkPayment.connect(Alice.signer).lockProof(proof.encodedProof, "0x0000000000000000000000000000000000000000")).fulfilled; + await expect(zkPayment.connect(Bob.signer).lockProof(proof.encodedProof, await Bob.signer.getAddress())).rejectedWith("Proof already locked by another party"); + await expect(zkPayment.connect(Alice.signer).lockProof(proof.encodedProof, await Bob.signer.getAddress())).fulfilled; + }); }); }).timeout(600000); From a203759e86052a898fcc87c985d976df969179cd Mon Sep 17 00:00:00 2001 From: Jim Zhang Date: Thu, 26 Sep 2024 13:58:48 -0400 Subject: [PATCH 3/3] Allow existing locks to be cleared Signed-off-by: Jim Zhang --- solidity/contracts/lib/zeto_common.sol | 6 +----- solidity/test/zkDvP.ts | 3 ++- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/solidity/contracts/lib/zeto_common.sol b/solidity/contracts/lib/zeto_common.sol index 0b2ea79..602afab 100644 --- a/solidity/contracts/lib/zeto_common.sol +++ b/solidity/contracts/lib/zeto_common.sol @@ -53,11 +53,7 @@ abstract contract ZetoCommon is OwnableUpgradeable { lockedProofs[proofHash] == msg.sender, "Proof already locked by another party" ); - if (delegate != address(0)) { - lockedProofs[proofHash] = delegate; - } else { - lockedProofs[proofHash] = msg.sender; - } + lockedProofs[proofHash] = delegate; } function sortInputsAndOutputs( diff --git a/solidity/test/zkDvP.ts b/solidity/test/zkDvP.ts index 4540473..4919d68 100644 --- a/solidity/test/zkDvP.ts +++ b/solidity/test/zkDvP.ts @@ -226,9 +226,10 @@ describe("DvP flows between fungible and non-fungible tokens based on Zeto with const utxo1 = newUTXO(100, Alice); const proof = await zetoAnonTests.prepareProof(circuit1, provingKey1, Alice, [utxo1, ZERO_UTXO], [utxo1, ZERO_UTXO], [Alice, {}]); - await expect(zkPayment.connect(Alice.signer).lockProof(proof.encodedProof, "0x0000000000000000000000000000000000000000")).fulfilled; + await expect(zkPayment.connect(Alice.signer).lockProof(proof.encodedProof, await Alice.signer.getAddress())).fulfilled; await expect(zkPayment.connect(Bob.signer).lockProof(proof.encodedProof, await Bob.signer.getAddress())).rejectedWith("Proof already locked by another party"); await expect(zkPayment.connect(Alice.signer).lockProof(proof.encodedProof, await Bob.signer.getAddress())).fulfilled; + await expect(zkPayment.connect(Bob.signer).lockProof(proof.encodedProof, "0x0000000000000000000000000000000000000000")).fulfilled; }); });