@@ -31,6 +31,12 @@ abstract contract MerkleBaseTest is Test, MurkyBase {
3131 _checkAllProofs (false );
3232 }
3333
34+ /// @notice Verifies that using wrong root fails verification
35+ function testFuzz_verifyInclusion_WrongRoot (uint ) public {
36+ root = bytes32 (vm.randomUint ());
37+ _checkAllProofs (false );
38+ }
39+
3440 /// @notice Verifies valid proofs cannot be used to prove invalid leaves.
3541 function testFuzz_verifyInclusion_WrongProofs (uint ) public {
3642 bytes memory proof0 = proofs[0 ];
@@ -43,8 +49,19 @@ abstract contract MerkleBaseTest is Test, MurkyBase {
4349 /// @notice Verifies that a valid proof with excess data appended is invalid.
4450 function testFuzz_verifyInclusion_ExcessProofLength (uint ) public {
4551 unchecked {
46- proofs[0 ] = abi.encodePacked (proofs[0 ], vm.randomBytes (vm.randomUint (1 , 10 ) * 32 ));
52+ proofs[0 ] = abi.encodePacked (proofs[0 ], vm.randomBytes (vm.randomUint (1 , 10 ) * vm.randomUint (31 , 32 )));
53+ }
54+ _checkSingleProof (false , 0 );
55+ }
56+
57+ /// @notice Verifies that a valid proof with a truncated length is invalid.
58+ function testFuzz_verifyInclusion_TruncatedProofLength (uint ) public {
59+ bytes memory proof = proofs[0 ];
60+ /// @solidity memory-safe-assembly
61+ assembly {
62+ mstore (proof, sub (mload (proof), 32 ))
4763 }
64+ proofs[0 ] = proof;
4865 _checkSingleProof (false , 0 );
4966 }
5067
@@ -68,8 +85,24 @@ abstract contract MerkleBaseTest is Test, MurkyBase {
6885 _checkSingleProof (false , index);
6986 }
7087
88+ /// @notice Verifies that an internal node cannot be used as a proof.
7189 function testFuzz_verifyInclusion_InternalNodeAsProof (uint ) public {
72- // TODO
90+ // Generate a tree with at least 4 leaves to ensure internal nodes exist
91+ leaves = _genLeaves (vm.randomUint (4 , 8 ));
92+ proofs = _genProofs (leaves);
93+ root = _genRoot (leaves);
94+ function (bytes memory proof , bytes32 root , bytes32 leaf , uint256 index ) view returns (bool ) verifyInclusion =
95+ usingSha () ? Merkle.verifyInclusionSha256 : Merkle.verifyInclusionKeccak;
96+ assertFalse (verifyInclusion (proofs[2 ], root, hashLeafPairs (leaves[0 ], leaves[1 ]), 2 ));
97+ }
98+
99+ /// @notice Verifies behavior with duplicate leaves in the tree
100+ function testFuzz_verifyInclusion_DuplicateLeaves (uint ) public {
101+ leaves = _genLeaves (vm.randomUint (4 , 8 ));
102+ leaves[0 ] = leaves[vm.randomUint (1 , leaves.length - 1 )];
103+ proofs = _genProofs (leaves);
104+ root = _genRoot (leaves);
105+ _checkAllProofs (true );
73106 }
74107
75108 /// -----------------------------------------------------------------------
@@ -81,7 +114,7 @@ abstract contract MerkleBaseTest is Test, MurkyBase {
81114 function (bytes memory proof , bytes32 root , bytes32 leaf , uint256 index ) returns (bool ) verifyInclusion =
82115 usingSha () ? Merkle.verifyInclusionSha256 : Merkle.verifyInclusionKeccak;
83116 for (uint i = 0 ; i < leaves.length ; ++ i) {
84- if (proofs[i].length == 0 ) vm.expectRevert (Merkle.InvalidProofLength.selector );
117+ if (proofs[i].length == 0 || proofs[i]. length % 32 != 0 ) vm.expectRevert (Merkle.InvalidProofLength.selector );
85118 assertEq (verifyInclusion (proofs[i], root, leaves[i], i), status);
86119 }
87120 }
@@ -90,7 +123,7 @@ abstract contract MerkleBaseTest is Test, MurkyBase {
90123 function _checkSingleProof (bool status , uint index ) internal virtual {
91124 function (bytes memory proof , bytes32 root , bytes32 leaf , uint256 index ) view returns (bool ) verifyInclusion =
92125 usingSha () ? Merkle.verifyInclusionSha256 : Merkle.verifyInclusionKeccak;
93- if (proofs[index].length == 0 ) vm.expectRevert (Merkle.InvalidProofLength.selector );
126+ if (proofs[index].length == 0 || proofs[index]. length % 32 != 0 ) vm.expectRevert (Merkle.InvalidProofLength.selector );
94127 assertEq (verifyInclusion (proofs[index], root, leaves[index], index), status);
95128 }
96129
@@ -107,7 +140,7 @@ abstract contract MerkleBaseTest is Test, MurkyBase {
107140 }
108141 }
109142
110- /// @dev Effeciently generates a random list of leaves without iterative hashing.
143+ /// @dev Generates a random list of leaves without iterative hashing.
111144 function _genLeaves (uint numLeaves ) internal view virtual returns (bytes32 [] memory leaves ) {
112145 bytes memory _leavesAsBytes = vm.randomBytes (numLeaves * 32 );
113146 /// @solidity memory-safe-assembly
0 commit comments