MyCut

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

Precision Loss in Reward Calculation Causes Dead Funds in Contract

Summary:

High Severity: The reward distribution calculation in the closePot function is susceptible to precision loss due to integer division, potentially leaving a small amount of tokens undisbursed and permanently locked in the contract as dead funds.

Vulnerability Details:

In the closePot function, the calculation of each claimant's share of the remaining rewards uses integer division:

uint256 claimantCut = (remainingRewards - managerCut) / i_players.length;

Since Solidity performs integer division, any remainder resulting from the division is discarded. This truncation leads to precision loss, where the total amount distributed does not exactly match the remainingRewards. As a result, a small number of tokens may remain in the contract after the distribution, which cannot be claimed or utilized and are effectively locked as dead funds.

Vulnerability Location:
Pot.sol: Line 57

Impact:

The impact of this vulnerability includes:

  • Dead Funds: Small amounts of tokens (remainders) can become permanently locked in the contract, reducing the efficiency of fund distribution.

  • Potential Financial Loss: Even small amounts of dead funds can accumulate over multiple distributions, leading to a significant total loss over time.

  • Inefficient Fund Management: The presence of dead funds could be perceived as poor management and a lack of precision in the contract's financial operations, potentially reducing user trust.

Tools Used:

  • Manual Review

Recommendations:

To mitigate this issue, the contract should include logic to handle any remainders left after dividing the rewards among claimants. These remainders could be redistributed in a way that prevents them from becoming dead funds or handled as part of the manager's cut or a future distribution. Although it still depends on the team how they choose to manage these funds, the following approach is one possible way to address the issue:

Updated Function Example to Handle Remainders:

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 totalClaimantCut = remainingRewards - managerCut;
uint256 baseCutPerClaimant = totalClaimantCut / claimants.length;
uint256 remainder = totalClaimantCut % claimants.length;
for (uint256 i = 0; i < claimants.length; i++) {
_transferReward(claimants[i], baseCutPerClaimant);
}
// Optionally, transfer the remainder to the manager to prevent dead funds
if (remainder > 0) {
i_token.transfer(msg.sender, remainder);
}
}
}

By implementing this logic, the contract ensures that any leftover tokens (remainders) are not permanently locked as dead funds, maintaining efficient fund management and full utilization of the pot's resources.

Updates

Lead Judging Commences

equious Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Dusty Pot

Support

FAQs

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