As we can see, the first 20 bytes of the salt has to be the address of the sender.
if (address(bytes20(salt)) != msg.sender) {
revert Errors.Create2Deployer_UnauthorizedSender(msg.sender, salt);
}
However, the function that calculates the salt does not do that. It returns the last 8 bytes of the sender, concatenated with bytes from data
function generateSaltWithSender(
address sender,
bytes12 data
) public pure returns (bytes32 salt) {
assembly {
// Use `or` to combine the bytes20 address and bytes12 data together.
salt := or(
// Shift the address 12 bytes to the left.
shl(0x60, sender),
// Shift the extra data 20 bytes to the right.
shr(0xA0, data)
)
}
}
Lines of code
https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/Create2Deployer.sol#L107-L119
Vulnerability details
Impact
Wrong salt returned from generateSaltWithSender() in Create2Deployer.sol.
Proof of Concept
As we can see, the first 20 bytes of the salt has to be the address of the sender.
However, the function that calculates the salt does not do that. It returns the last 8 bytes of the sender, concatenated with bytes from
data
Tools Used
Manual Review
Recommended Mitigation Steps
Make the function return the correct salt.
Assessed type
Error