ContestManager.fundContest() and Pot._transferReward() use raw ERC20 transferFrom/transfer and ignore returned bool.
When token returns false (without revert), state still advances:
contest appears funded when it is not
claim accounting is reduced even when payout did not happen
Affected lines:
src/ContestManager.sol → token.transferFrom(msg.sender, address(pot), totalRewards);
src/Pot.sol → i_token.transfer(player, reward);
Likelihood: Medium
Protocol accepts generic IERC20 behavior.
False-return tokens exist in production and integrations.
Impact: High
Silent underfunding of pots.
playersToRewards[player] can be zeroed while claimant receives no tokens.
Accounting drift and effective reward loss.
Created deterministic tests using a false-returning mock token.
Files:
test/FalseReturnERC20Mock.sol
test/MyCutSecondPassFindings.t.sol
Repro 1 (funding fails silently):
Create contest with totalRewards = 100.
Call fundContest(0).
transferFrom returns false, no revert.
Assert balanceOf(pot) == 0.
Repro 2 (claim burns accounting without payout):
Setup contest where player1 reward is 60.
Call player1.claimCut().
transfer returns false, no revert.
Assert:
checkCut(player1): 60 -> 0
remainingRewards decreased by 60
player1 token balance unchanged.
Validation command:
Use OpenZeppelin SafeERC20 everywhere transfers occur and enforce transfer success by revert semantics.
Add post-condition checks on critical paths (funding / claim / close)
Ensure expected token delta on recipient matches accounted reward change
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.