Description: In InheritanceManager::buyOutEstateNFT
, the calculation '(value / divisor) * multiplier' performs division before multiplication. Since Solidity uses integer division, truncation can occur if 'value' is not perfectly divisible by 'divisor'.
Impact: Beneficiaries may receive less than their intended share due to precision loss. This can lead to financial discrepancies and disputes among beneficiaries.
Proof of Concept: Include the following test in the InheritanceManagerTest.t.sol
file:
function testBuyOutEstateNFTPrecisionLoss() public {
address user2 = makeAddr("user2");
address user3 = makeAddr("user3");
address user4 = makeAddr("user4");
address user5 = makeAddr("user5");
vm.warp(1);
im.addBeneficiery(user1);
im.addBeneficiery(user2);
im.addBeneficiery(user3);
im.addBeneficiery(user4);
im.addBeneficiery(user5);
uint256 nftValue = 3;
im.createEstateNFT("our beach-house", nftValue, address(usdc));
uint256 startAmount = 1e6;
usdc.mint(user5, startAmount);
vm.warp(1 + 90 days);
vm.startPrank(user5);
usdc.approve(address(im), startAmount);
im.inherit();
im.buyOutEstateNFT(1);
vm.stopPrank();
uint256 userBalanceAfterBuyOut = usdc.balanceOf(user5);
assertEq(startAmount, userBalanceAfterBuyOut);
}
Recommended Mitigation: Reorder the calculation to perform multiplication before division:
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;
...
}