The function assumes that the Merkle tree is balanced. If the tree is not balanced, the verification might not work correctly.
Vulnerability Detail
let end := add(proof.offset, shl(5, proof.length))
// set iterator to the start of the proof array
let i := proof.offset
// prettier-ignore
// solhint-disable-next-line no-empty-blocks
for {} 1 {} {
// if index is odd, leaf slot is at 0x20, else 0x0
let leafSlot := shl(5, and(0x1, index))
// store the leaf at the calculated slot
mstore(leafSlot, leaf)
// store proof element in whichever slot is not occupied by the leaf
mstore(xor(leafSlot, 32), calldataload(i))
// hash the first 64 bytes in memory
leaf := keccak256(0, 64)
// shift index right by 1 bit to divide by 2
index := shr(1, index)
// increment iterator by 32 bytes
i := add(i, 32)
// break if iterator is at the end of the proof array
if iszero(lt(i, end)) { break }
}
}
// check if index is zeroed out (because tree is balanced) and leaf is equal to root
isValid := and(eq(leaf, root), iszero(index))
}
Impact
If the tree is not balanced, the verification might not work correctly.
bareli
medium
Merkle tree is balanced
Summary
The function assumes that the Merkle tree is balanced. If the tree is not balanced, the verification might not work correctly.
Vulnerability Detail
let end := add(proof.offset, shl(5, proof.length)) // set iterator to the start of the proof array let i := proof.offset // prettier-ignore // solhint-disable-next-line no-empty-blocks for {} 1 {} { // if index is odd, leaf slot is at 0x20, else 0x0 let leafSlot := shl(5, and(0x1, index)) // store the leaf at the calculated slot mstore(leafSlot, leaf) // store proof element in whichever slot is not occupied by the leaf mstore(xor(leafSlot, 32), calldataload(i)) // hash the first 64 bytes in memory leaf := keccak256(0, 64) // shift index right by 1 bit to divide by 2 index := shr(1, index) // increment iterator by 32 bytes i := add(i, 32) // break if iterator is at the end of the proof array if iszero(lt(i, end)) { break } } } // check if index is zeroed out (because tree is balanced) and leaf is equal to root isValid := and(eq(leaf, root), iszero(index)) }
Impact
If the tree is not balanced, the verification might not work correctly.
Code Snippet
https://github.com/sherlock-audit/2023-12-avail/blob/main/contracts/src/lib/Merkle.sol#L42
Tool used
Manual Review
Recommendation