The _transferReward() function uses IERC20.transfer() but does not check the return value. Standard ERC20 transfer() returns a boolean indicating success or failure. If the transfer fails silently (returns false), the contract state is still updated (in claimCut()), but the user receives nothing.
While some tokens revert on failure, the ERC20 standard specifies that transfer() should return false on failure. Not checking the return value means the contract cannot handle failed transfers properly.
This is called from claimCut() which updates state before the transfer (good CEI pattern), but if the transfer fails, the user's state is already updated (playersToRewards[player] = 0, remainingRewards -= reward, claimants.push(player)), and they cannot claim again.
Likelihood: Medium - Depends on the token used; some tokens may fail transfers without reverting.
Impact:
Users may lose their rewards if transfer fails silently
State is updated but no tokens are sent
Users cannot reclaim lost rewards (state already updated)
This POC demonstrates that when transfer() fails silently (returns false), the player's state is already updated (playersToRewards[player] = 0), but they receive no tokens and cannot claim again.
Using OpenZeppelin's SafeERC20 library ensures that failed transfers revert the transaction, preventing state updates when tokens are not actually sent.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.