The claimAllRewards() and claimSingleReward() functions are vulnerable to reentrancy attacks due to improper ordering of state changes and external calls.
Affected Code in claimAllRewards():
Issue: The external call to transfer Ether occurs before updating the user's rewards.
Consequence: An attacker can re-enter the function via a fallback function before their rewards are cleared.
An attacker deploys a malicious contract (AttackContract) with a fallback function that calls claimAllRewards() recursively:
Attacker's Setup:
Accumulates rewards in mysteryBox.
Deploys AttackContract and sets msg.sender to AttackContract.
Attack Execution:
Calls mysteryBox.claimAllRewards() from AttackContract.
Reentrancy:
During the Ether transfer, AttackContract's receive() function is triggered.
receive() calls mysteryBox.claimAllRewards() again before rewardsOwned[msg.sender] is cleared.
Result:
The attacker withdraws funds multiple times.
Drains the contract's balance.
Malicious Contract Example:
We can write a test to simulate the reentrancy attack:
Financial Loss: The attacker can drain all Ether from the contract.
Contract Disruption: Other users cannot claim rewards due to depleted funds.
Reputation Damage: Loss of trust in the contract's security.
Manual Code Review: Identified improper ordering in the function.
Testing Framework (Foundry): Simulated the attack with a malicious contract.
Implement the Checks-Effects-Interactions pattern and use OpenZeppelin's ReentrancyGuard:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.