Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: low
Valid

Remainder Funds Stuck in Contract

Summary

This vulnerability leads to funds being permanently stuck in the contract due to Solidity's integer division behavior

Vulnerability Details

The withdrawInheritedFunds function in InheritanceManager.sol contract is designed to distribute inherited ETH or ERC20 tokens among beneficiaries. However, due to Solidity's integer division, any remainder from the division is left in the contract, leading to fund accumulation over time.

Root Cause

Solidity performs integer division, meaning any remainder from the division (assetAmountAvailable / divisor) or (ethAmountAvailable / divisor) will remain in the contract instead of being distributed. This results in an accumulation of unclaimed funds over multiple transactions.

Affected Lines of Code

uint256 amountPerBeneficiary = ethAmountAvailable / divisor;
...
uint256 amountPerBeneficiary = assetAmountAvailable / divisor;

Impact

Financial loss due to accumulation of unclaimed funds, creating potential legal or operational issues as integer division is inherent to Solidity and affects all transactions.

  • Trapped Funds: Over time, the contract accumulates ETH or ERC20 tokens that remain undistributed.

  • Financial Loss: Beneficiaries receive slightly less than their actual share, leading to dissatisfaction and legal disputes.

  • Contract Dysfunction: Future withdrawals may be affected if the contract depends on a precise balance.

  • Dust Accumulation: These funds may be too small to be withdrawn through any other means, leading to irretrievable assets.

Proof of Concept (PoC)

Scenario:

  1. Assume the contract holds 100 wei and has 3 beneficiaries.

  2. The division calculation: 100 / 3 = 33 wei per beneficiary.

  3. The remainder (100 % 3 = 1 wei) remains in the contract forever.

  4. After multiple withdrawals, these small remainders accumulate, making the contract inefficient.

Tools Used

manual review

Recommendations

Implement logic to distribute the remainder to one of the beneficiaries (e.g., the first or last in the list):

uint256 remainder = ethAmountAvailable % divisor;
if (remainder > 0) {
payable(beneficiaries[0]).transfer(remainder);
}

Also for ERC20 tokens

uint256 remainder = assetAmountAvailable % divisor;
if (remainder > 0) {
IERC20(_asset).safeTransfer(beneficiaries[0], remainder);
}
Updates

Lead Judging Commences

0xtimefliez Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

truncation of integers

Support

FAQs

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