The contract Snowman.sol utilizes abi.encodePacked() with multiple dynamic arguments within a keccak256() hash function, which can lead to hash collisions.
In src/Snowman.sol at lines 54 and 57, the code uses abi.encodePacked() to concatenate data before hashing it. When abi.encodePacked() is used with multiple dynamic types (such as string or bytes), it does not include any padding between the elements.
This lack of padding allows different sets of input data to produce the exact same output hash. For example, the following two distinct inputs will result in a collision:
keccak256(abi.encodePacked("a", "bc"))
keccak256(abi.encodePacked("ab", "c"))
Both operations result in the same concatenated bytes before hashing, leading to an identical bytes32 result.
A malicious actor could exploit this collision to bypass security checks or provide fraudulent data that matches an existing hash. In the context of Merkle trees or signatures, this could allow for the creation of unauthorized proofs.
To demonstrate the collision, you can run a simple Chisel session or a Foundry test:
Replace abi.encodePacked() with abi.encode(), which implements proper padding to 32 bytes for each argument, thereby ensuring unique hash outputs for unique inputs. Alternatively, for concatenating only strings or bytes, consider using bytes.concat().
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.