@@ -15,37 +15,65 @@ abstract contract MerkleBaseTest is Test, MurkyBase {
1515 /// Keccak + Sha256 Tests
1616 /// -----------------------------------------------------------------------
1717
18- /// @notice Verifies that Murky's proofs are compatible with our tree and proof verification .
19- function test_verifyInclusion_ValidProof ( ) public {
20- assertValidProofs ( );
18+ /// @notice Verifies that ( Murky's) proofs are compatible with our implementation .
19+ function testFuzz_verifyInclusion_ValidProof ( uint ) public {
20+ checkAllProofs ( true );
2121 }
2222
2323 /// @notice Verifies that an empty proof(s) is invalid.
24- function test_verifyInclusion_EmptyProofs ( ) public {
24+ function testFuzz_verifyInclusion_EmptyProofs ( uint ) public {
2525 proofs = new bytes [](proofs.length );
26- assertInvalidProofs ();
26+ checkAllProofs (false );
27+ }
28+
29+ /// @notice Verifies valid proofs cannot be used to prove invalid leaves.
30+ function testFuzz_verifyInclusion_WrongProofs (uint ) public {
31+ bytes memory proof0 = proofs[0 ];
32+ bytes memory proof1 = proofs[1 ];
33+ (proofs[0 ], proofs[1 ]) = (proof1, proof0);
34+ checkSingleProof (false , 0 );
35+ checkSingleProof (false , 1 );
36+ }
37+
38+ /// @notice Verifies that a valid proof with excess data appended is invalid.
39+ function testFuzz_verifyInclusion_ExcessProofLength (uint ) public {
40+ unchecked {
41+ proofs[0 ] = abi.encodePacked (proofs[0 ], vm.randomBytes (vm.randomUint (1 , 10 ) * 32 ));
42+ }
43+ checkSingleProof (false , 0 );
44+ }
45+
46+ /// @notice Verifies that a valid proof with a manipulated word is invalid.
47+ function testFuzz_verifyInclusion_ManipulatedProof (uint ) public {
48+ bytes memory proof = proofs[0 ];
49+ /// @solidity memory-safe-assembly
50+ assembly {
51+ let m := add (proof, 0x20 )
52+ let manipulated := shr (8 , mload (m)) // Shift the first word to the right by 8 bits.
53+ mstore (m, manipulated)
54+ }
55+ proofs[0 ] = proof;
56+ checkSingleProof (false , 0 );
2757 }
2858
2959 /// -----------------------------------------------------------------------
3060 /// Assertions
3161 /// -----------------------------------------------------------------------
3262
3363 /// @dev Checks that all proofs are valid for their respective leaves.
34- function assertValidProofs ( ) internal virtual {
64+ function checkAllProofs ( bool status ) internal virtual {
3565 function (bytes memory proof , bytes32 root , bytes32 leaf , uint256 index ) returns (bool ) verifyInclusion =
3666 usingSha ? Merkle.verifyInclusionSha256 : Merkle.verifyInclusionKeccak;
3767 for (uint i = 0 ; i < leaves.length ; ++ i) {
38- assertTrue (verifyInclusion (proofs[i], root, leaves[i], i), " invalid proof " );
68+ assertEq (verifyInclusion (proofs[i], root, leaves[i], i), status );
3969 }
4070 }
4171
42- /// @dev Checks that all proofs are invalid for their respective leaves .
43- function assertInvalidProofs ( ) internal virtual {
72+ /// @dev Checks that a single proof is valid for its respective leaf .
73+ function checkSingleProof ( bool status , uint index ) internal virtual {
4474 function (bytes memory proof , bytes32 root , bytes32 leaf , uint256 index ) returns (bool ) verifyInclusion =
4575 usingSha ? Merkle.verifyInclusionSha256 : Merkle.verifyInclusionKeccak;
46- for (uint i = 0 ; i < leaves.length ; ++ i) {
47- assertFalse (verifyInclusion (proofs[i], root, leaves[i], i), "valid proof " );
48- }
76+ assertEq (verifyInclusion (proofs[index], root, leaves[index], index), status);
4977 }
5078
5179 /// -----------------------------------------------------------------------
0 commit comments