Closed sherlock-admin4 closed 1 month ago
First of all the usage of "Replay Attack" here is pretty weird as it doesn't seem it is understood what it means. Secondly this is not a bug, if the contract was already created, it is ok to revert when trying to do it again. There is not a denial of service at all, the msg.sender already has a voteDelegate created.
JuggerNaut63
Medium
Replay Attack in VoteDelegateFactory Contract Creation Mechanism
Summary
create
function uses a deterministic salt derived frommsg.sender
for thecreate2
opcode. This approach can lead to replay attacks, where the same user can only create oneVoteDelegate
contract, and any subsequent attempts will fail due to address collision.Vulnerability Detail
Issue: The
create
function usescreate2
with a salt derived frommsg.sender
:Problem: If the same user (
msg.sender
) callscreate
more than once, the salt remains the same, leading to the same contract address being generated. Since the address is already occupied by the first contract creation, subsequent calls will fail.Impact
Code Snippet
https://github.com/sherlock-audit/2024-06-makerdao-endgame/blob/main/vote-delegate/src/VoteDelegateFactory.sol#L61-L66
Tool used
Manual Review
Recommendation
VoteDelegate
does not already exist for the user before allowing the creation of a new one. This prevents the replay attack by ensuring only oneVoteDelegate
per user.require(created[getAddress(msg.sender)] == 0, "VoteDelegate already exists"); voteDelegate = address(new VoteDelegate{salt: bytes32(uint256(uint160(msg.sender)))}(chief, polling, msg.sender)); created[voteDelegate] = 1;
emit CreateVoteDelegate(msg.sender, voteDelegate); }
create2
call generates a unique address, even for the same user.voteDelegate = address(new VoteDelegate{salt: salt}(chief, polling, msg.sender)); created[voteDelegate] = 1;
emit CreateVoteDelegate(msg.sender, voteDelegate); }
function create() external returns (address voteDelegate) {
voteDelegate = address(new VoteDelegate{salt: salt}(chief, polling, msg.sender)); created[voteDelegate] = 1;
emit CreateVoteDelegate(msg.sender, voteDelegate); }