MyCut

First Flight #23
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: high
Invalid

Unclaimed rewards permanently locked due to failure in individual transfers

Summary

The Pot::closePot function is responsible for distributing the remaining rewards to the claimants after the contest has been closed. However, if any of the claimants are unable to receive the reward tokens, for example, due to being on a blacklist, the entire transaction will revert, preventing the contest from being closed and locking all remaining funds in the contract.

Vulnerability Details

In the Pot::closePot function, the remaining rewards are distributed to the claimants using the _transferReward function:

function closePot() external onlyOwner {
if (block.timestamp - i_deployedAt < 90 days) {
revert Pot__StillOpenForClaim();
}
if (remainingRewards > 0) {
uint256 managerCut = remainingRewards / managerCutPercent;
i_token.transfer(msg.sender, managerCut);
uint256 claimantCut = (remainingRewards - managerCut) / i_players.length;
for (uint256 i = 0; i < claimants.length; i++) {
@> _transferReward(claimants[i], claimantCut);
}
}
}

The _transferReward function is defined as follows:

function _transferReward(address player, uint256 reward) internal {
i_token.transfer(player, reward);
}

If any of the claimants are unable to receive the tokens, for example, due to being on a blacklist, the i_token.transfer call will revert, causing the entire closePot function to revert. This will prevent the contest from being closed, and the remaining rewards will be permanently locked in the contract.

Impact

If any of the claimants are unable to receive their reward tokens, the entire closePot function will revert, preventing the contest from being closed and locking all remaining funds in the contract. This means that neither the claimants nor the contest manager will be able to access the locked funds.

Tools Used

Manual Code Review

Recommendations

To mitigate this issue, the _transferReward function should be modified to handle individual failed transfers without causing the entire function to revert. One approach is to use a try-catch block to catch any exceptions and continue with the distribution of rewards to the remaining claimants.

function _transferReward(address player, uint256 reward) internal {
try i_token.transfer(player, reward) {
// Transfer successful
} catch {
// Transfer failed, skip this player and continue with the next
}
}

By handling individual failed transfers in this way, the closePot function will be able to distribute the remaining rewards to the claimants who can successfully receive them, without the entire process being blocked by a single failed transfer.

Updates

Lead Judging Commences

equious Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Other

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.