Przeglądaj źródła

Fix merkle multiProof for single leaf tree (#3446)

Hadrien Croubois 3 lat temu
rodzic
commit
2b0b0bb186

+ 7 - 1
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) {

+ 20 - 0
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);
+    });
   });
 });