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

Incorrect Fund Distribution in InheritanceManager::buyOutEstateNFT Due to Wrong Denominator

Summary

The InheritManager::buyOutEstateNFT function uses divisor (total number of beneficiaries) instead of multiplier (number of beneficiaries excluding the buyer) when distributing funds to beneficiaries. This results in beneficiaries receiving less than their fair share of the payment, while the contract retains unallocated funds.

POC

Place this test in the test/InheritanceManagerTest.t.sol:

function test_unfair_share_due_to_wrong_denominator() external {
address user2 = makeAddr("user2");
address user3 = makeAddr("user3");
vm.warp(1);
vm.startPrank(owner);
im.addBeneficiery(user1);
im.addBeneficiery(user2);
im.addBeneficiery(user3);
im.createEstateNFT("our beach-house", 3e6, address(usdc));
vm.stopPrank();
usdc.mint(user3, 4e6);
vm.warp(1 + 90 days);
// make sure other beneficiaries have 0 usdc
assertEq(usdc.balanceOf(user1), 0);
assertEq(usdc.balanceOf(user2), 0);
vm.startPrank(user3);
usdc.approve(address(im), 4e6);
im.inherit();
im.buyOutEstateNFT(1);
vm.stopPrank();
uint256 expectedShare = im.getNftValue(1) / 3;
// share given to beneficiaries is less than expected share
assertLt(usdc.balanceOf(user1), expectedShare);
uint256 amountLost = 333334;
assertEq(expectedShare, usdc.balanceOf(user1) + amountLost);
}

Impact

Beneficiaries receive less than their fair share of the payment, leading to financial losses.

Tools Used

  • Manual Review

Recommendations

Use multiplier (not divisor) when distributing funds to beneficiaries. Update the distribution logic as follows:

function buyOutEstateNFT(uint256 _nftID) external onlyBeneficiaryWithIsInherited {
uint256 value = nftValue[_nftID];
uint256 divisor = beneficiaries.length;
uint256 multiplier = beneficiaries.length - 1;
- uint256 finalAmount = (value / divisor) * multiplier;
+ uint256 finalAmount = (value * multiplier) / divisor; // this is another issue
IERC20(assetToPay).safeTransferFrom(msg.sender, address(this), finalAmount);
for (uint256 i = 0; i < beneficiaries.length; i++) {
- if (msg.sender == beneficiaries[i]) {
- return;
- } else {
- IERC20(assetToPay).safeTransfer(beneficiaries[i], finalAmount / divisor);
- }
+ if (msg.sender != beneficiaries[i]) {
+ IERC20(assetToPay).safeTransfer(beneficiaries[i], finalAmount / multiplier); // main issue
+ }
}
nft.burnEstate(_nftID);
}
Updates

Lead Judging Commences

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

buyOutNFT has wrong denominator

Support

FAQs

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