MyCut

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

`Pot::_transferReward(address,uint256)` has external calls inside a loop: `i_token.transfer(player,reward)` making it vulnerable to a denial-of-service attack.

Summary

The _transferReward() function itself is not directly vulnerable to a denial-of-service (DoS) attack, as it simply calls the transfer function on the ERC20 token contract. However, unusual behavior or restrictions (e.g., blacklisting addresses, transfer limits), resulting in unsuccessful transfers, and token transfer failure could creates the functional failure.

Vulnerability Details

uint256 claimantCut = (remainingRewards - managerCut) / i_players.length;
for (uint256 i = 0; i < claimants.length; i++) {
_transferReward(claimants[i], claimantCut);
}
.
.
.
function _transferReward(address player, uint256 reward) internal {
i_token.transfer(player, reward);
}

Impact

If the ERC20 token contract has unusual behavior or restrictions (e.g., blacklisting addresses, transfer limits), it could prevent successful transfers, effectively causing a DoS for affected users.

Tools Used

Slither

Recommendations

Implementing a pull over push strategy involves allowing users to withdraw their rewards themselves, rather than the contract automatically sending rewards to them. This can help mitigate issues like failed transfers and gas limitations. A strategy to implement this is to store rewards, modify claimCut(), and add a withdrawReward() function.

// Mapping to store claimable rewards
- mapping(address => uint256) public contestToTotalRewards;
+ mapping(address => uint256) private claimableRewards;
// Modify claimCut() to update claimable rewards
function claimCut() public {
address player = msg.sender;
uint256 reward = playersToRewards[player];
if (reward <= 0) {
revert Pot__RewardNotFound();
}
playersToRewards[player] = 0;
remainingRewards -= reward;
- claimants.push(player);
- _transferReward(player, reward);
+ claimableRewards[player] += reward; // Update claimable rewards
}
// New function to allow players to withdraw their rewards
function withdrawReward() public {
uint256 reward = claimableRewards[msg.sender];
require(reward > 0, "No rewards to withdraw");
claimableRewards[msg.sender] = 0; // Reset claimable rewards
_transferReward(msg.sender, reward);
}
Updates

Lead Judging Commences

equious Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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