From 2b0b0bb186df0a0b575dced8d15262ec5e90211c Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Wed, 1 Jun 2022 22:21:56 +0200 Subject: [PATCH] Fix merkle multiProof for single leaf tree (#3446) --- contracts/utils/cryptography/MerkleProof.sol | 8 +++++++- test/utils/cryptography/MerkleProof.test.js | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/contracts/utils/cryptography/MerkleProof.sol b/contracts/utils/cryptography/MerkleProof.sol index ea4217c8e..21d64c00a 100644 --- a/contracts/utils/cryptography/MerkleProof.sol +++ b/contracts/utils/cryptography/MerkleProof.sol @@ -105,7 +105,13 @@ library MerkleProof { hashes[i] = _hashPair(a, b); } - return hashes[totalHashes - 1]; + if (totalHashes > 0) { + return hashes[totalHashes - 1]; + } else if (leafsLen > 0) { + return leafs[0]; + } else { + return proofs[0]; + } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { diff --git a/test/utils/cryptography/MerkleProof.test.js b/test/utils/cryptography/MerkleProof.test.js index 069d79221..c3adfb34c 100644 --- a/test/utils/cryptography/MerkleProof.test.js +++ b/test/utils/cryptography/MerkleProof.test.js @@ -127,5 +127,25 @@ contract('MerkleProof', function (accounts) { 'reverted with panic code 0x32', ); }); + + it('limit case: works for tree containing a single leaf', async function () { + const leaves = ['a'].map(keccak256).sort(Buffer.compare); + const merkleTree = new MerkleTree(leaves, keccak256, { sort: true }); + + const root = merkleTree.getRoot(); + const proofLeaves = ['a'].map(keccak256).sort(Buffer.compare); + const proof = merkleTree.getMultiProof(proofLeaves); + const proofFlags = merkleTree.getProofFlags(proofLeaves, proof); + + expect(await this.merkleProof.multiProofVerify(root, proofLeaves, proof, proofFlags)).to.equal(true); + }); + + it('limit case: can prove empty leaves', async function () { + const leaves = ['a', 'b', 'c', 'd'].map(keccak256).sort(Buffer.compare); + const merkleTree = new MerkleTree(leaves, keccak256, { sort: true }); + + const root = merkleTree.getRoot(); + expect(await this.merkleProof.multiProofVerify(root, [], [ root ], [])).to.equal(true); + }); }); });