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

Division Truncation Error in withdrawInheritedFunds() in InheritanceManager

Summary

The function divides the total available balance (ethAmountAvailable or assetAmountAvailable) by the number of beneficiaries (divisor). However, Solidity division truncates the result, which can lead to loss of funds if the total balance is not perfectly divisible by the number of beneficiaries.

Vulnerability Details

  • The division ethAmountAvailable / divisor and assetAmountAvailable / divisor truncates any remainder.

  • For example, if ethAmountAvailable = 101 and divisor = 3, each beneficiary receives 33 wei, and 2 wei are left unallocated in the contract.

function withdrawInheritedFunds(address _asset) external {
if (!isInherited) {
revert NotYetInherited();
}
uint256 divisor = beneficiaries.length;
if (_asset == address(0)) {
uint256 ethAmountAvailable = address(this).balance;
uint256 amountPerBeneficiary = ethAmountAvailable / divisor; // loss of funds here
for (uint256 i = 0; i < divisor; i++) {
address payable beneficiary = payable(beneficiaries[i]);
(bool success,) = beneficiary.call{value: amountPerBeneficiary}("");
require(success, "something went wrong");
}
} else {
uint256 assetAmountAvailable = IERC20(_asset).balanceOf(address(this));
uint256 amountPerBeneficiary = assetAmountAvailable / divisor;
for (uint256 i = 0; i < divisor; i++) {
IERC20(_asset).safeTransfer(beneficiaries[i], amountPerBeneficiary);
}
}
}

Impact

  • Loss of Funds: A small amount of Ether or tokens may remain stuck in the contract, inaccessible to beneficiaries.

  • Inequitable Distribution: Beneficiaries may not receive their fair share of the funds.

Tools Used

  • Manual code review

Recommendations

Distribute the remainder to one of the beneficiaries (e.g., the first or last) to ensure all funds are allocated.

uint256 amountPerBeneficiary = ethAmountAvailable / divisor;
uint256 remainder = ethAmountAvailable % divisor;
for (uint256 i = 0; i < divisor; i++) {
uint256 amount = amountPerBeneficiary + (i == 0 ? remainder : 0);
(bool success,) = payable(beneficiaries[i]).call{value: amount}("");
require(success, "Transfer failed");
}

The recommended approach ensures that:

  1. Each beneficiary receives an equal share (amountPerBeneficiary).

  2. Only one beneficiary (e.g., the first) receives the additional remainder.

  3. The total distributed amount matches the available balance.

Updates

Lead Judging Commences

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

buyOutNFT has wrong denominator

truncation of integers

Support

FAQs

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