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

Deadline Reset Omissions in Owner Functions

Summary

Owner-initiated functions in the InheritanceManager contract—specifically contractInteractions, createEstateNFT, and removeBeneficiary—fail to update the inactivity deadline, which is intended to reset on every owner action.

Vulnerability Details

The contract’s design expects that every action performed by the owner resets the 90-day inactivity timer via a call to _setDeadline(). However, these functions omit the deadline update, allowing the contract to continue using an outdated deadline. This flaw can be exploited by an attacker or a beneficiary to trigger the inheritance process prematurely, even when the owner is actively managing the contract.

Impact

Direct Impact: Funds can be inherited earlier than intended, leading to loss of owner control.

Tools Used

Manual review

Foundry (Forge) for unit testing

Custom Forge tests demonstrating unchanged deadline values

Recommendations

Update the contractInteractions, createEstateNFT, and removeBeneficiary functions to call _setDeadline() immediately after successful execution.

PoC

pragma solidity 0.8.26;
import {Test} from "forge-std/Test.sol";
import {InheritanceManager} from "../src/InheritanceManager.sol";
import {ERC20Mock} from "@openzeppelin/contracts/mocks/token/ERC20Mock.sol";
contract InheritanceManagerVulnerabilityTest is Test {
InheritanceManager im;
ERC20Mock usdc;
ERC20Mock weth;
address owner = makeAddr("owner");
address beneficiary1 = makeAddr("beneficiary1");
address beneficiary2 = makeAddr("beneficiary2");
address attacker = makeAddr("attacker");
uint256 public constant INITIAL_SUPPLY = 1000e18;
uint256 public constant ASSET_VALUE = 100e18;
function setUp() public {
vm.prank(owner);
im = new InheritanceManager();
// Deploy mocks with an initial supply for testing
usdc = new ERC20Mock();
weth = new ERC20Mock();
usdc.mint(owner, INITIAL_SUPPLY);
weth.mint(owner, INITIAL_SUPPLY);
}
/// @notice Test that `contractInteractions` does not update the inactivity deadline.
function test_deadlineNotUpdatedInContractInteractions() public {
// Arrange
vm.prank(owner);
im.addBeneficiery(beneficiary1);
uint256 originalDeadline = im.getDeadline();
// Act
// Call contractInteractions with a dummy target and empty payload.
vm.prank(owner);
im.contractInteractions(address(0x123), hex"", 0, true);
// Assert
uint256 newDeadline = im.getDeadline();
// Expect the deadline to remain unchanged (vulnerability).
assertEq(
originalDeadline,
newDeadline,
"Deadline expected to not be updated in contractInteractions"
);
}
/// @notice Test that `createEstateNFT` does not update the inactivity deadline.
function test_deadlineNotUpdatedInCreateEstateNFT() public {
// Arrange
vm.prank(owner);
im.addBeneficiery(beneficiary1);
uint256 deadlineBefore = im.getDeadline();
// Act
vm.prank(owner);
im.createEstateNFT("Test NFT", ASSET_VALUE, address(usdc));
// Assert
uint256 deadlineAfter = im.getDeadline();
// The deadline remains unchanged, which is unexpected behavior.
assertEq(
deadlineAfter,
deadlineBefore,
"Deadline expected to not be updated in createEstateNFT"
);
}
/// @notice Test that `removeBeneficiary` does not update the inactivity deadline.
function test_deadlineNotUpdatedInRemoveBeneficiary() public {
// Arrange
vm.prank(owner);
im.addBeneficiery(beneficiary1);
uint256 deadlineBefore = im.getDeadline();
vm.warp(3600);
// Act
vm.prank(owner);
im.removeBeneficiary(beneficiary1);
// Assert
uint256 deadlineAfter = im.getDeadline();
assertEq(
deadlineAfter,
deadlineBefore,
"Deadline expected to not be updated in removeBeneficiary"
);
}
}
Updates

Lead Judging Commences

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

functions do not reset the deadline

Support

FAQs

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