function buyOutEstateNFT(uint256 _nftID) external onlyBeneficiaryWithIsInherited {
uint256 value = nftValue[_nftID];
uint256 divisor = beneficiaries.length;
uint256 multiplier = beneficiaries.length - 1;
uint256 finalAmount = (value / divisor) * multiplier;
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);
}
}
nft.burnEstate(_nftID);
}
pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "../src/InheritanceManager.sol";
import "../src/NFTFactory.sol";
import "../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
contract MockERC20 is ERC20 {
constructor() ERC20("MockToken", "MTK") {
_mint(msg.sender, 1_000_000 ether);
}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
}
contract InheritanceManagerBugTest is Test {
InheritanceManager public manager;
MockERC20 public token;
address public owner;
address public beneficiary1;
address public beneficiary2;
address public beneficiary3;
function setUp() public {
owner = address(0xABCD);
beneficiary1 = address(0xBEEF);
beneficiary2 = address(0xCAFE);
beneficiary3 = address(0xDEAD);
vm.prank(owner);
manager = new InheritanceManager();
token = new MockERC20();
vm.startPrank(owner);
manager.addBeneficiery(beneficiary1);
manager.addBeneficiery(beneficiary2);
manager.addBeneficiery(beneficiary3);
manager.createEstateNFT("Estate A", 90_000 ether, address(token));
vm.stopPrank();
skip(91 days);
vm.prank(beneficiary1);
manager.inherit();
}
function testBuyOutBug_RewardsOnlySomeBeneficiaries() public {
uint256 nftID = 0;
uint256 expectedPayment = 90_000 ether * (3 - 1) / 3;
token.mint(beneficiary1, expectedPayment);
vm.startPrank(beneficiary1);
token.approve(address(manager), expectedPayment);
manager.buyOutEstateNFT(nftID);
vm.stopPrank();
uint256 beneficiary2Balance = token.balanceOf(beneficiary2);
uint256 beneficiary3Balance = token.balanceOf(beneficiary3);
emit log_named_uint("Beneficiary2 balance", beneficiary2Balance);
emit log_named_uint("Beneficiary3 balance", beneficiary3Balance);
assertEq(beneficiary2Balance, 30_000 ether, "Beneficiary2 should have received 30k ether");
assertEq(beneficiary3Balance, 30_000 ether, "Beneficiary3 should have received 30k ether");
}
}
function buyOutEstateNFT(uint256 \_nftID) external onlyBeneficiaryWithIsInherited {
uint256 value = nftValue\[\_nftID];
uint256 divisor = beneficiaries.length;
uint256 multiplier = beneficiaries.length - 1;
uint256 finalAmount = (value / divisor) \* multiplier;
IERC20(assetToPay).safeTransferFrom(msg.sender, address(this), finalAmount);
for (uint256 i = 0; i < beneficiaries.length; i++) {
if (msg.sender == beneficiaries[i]) {
continue;
}
IERC20(assetToPay).safeTransfer(beneficiaries[i], finalAmount / multiplier);
}
nft.burnEstate(_nftID);
}