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

Missing deadline reset in owner functions breaks inactivity timer invariant

Summary

The InheritanceManager contract intends to reset the 90-day inactivity timer (via _setDeadline) with every owner-initiated transaction, ensuring the timer reflects the owner’s last activity. However, several owner-controlled functions fail to call _setDeadline, allowing the timer to expire prematurely despite recent owner activity. This could enable beneficiaries or attackers to trigger inheritance (inherit) sooner than intended, potentially leading to unauthorized fund withdrawal or ownership transfer.

Vulnerability Details

The contract use a deadline state variable and updates it by internal function setDeadline to track owner inactivity.

uint256 deadline;
uint256 public constant TIMELOCK = 90 days;
function _setDeadline() internal {
deadline = block.timestamp + TIMELOCK;
}

There is an invariant which states that every owner transaction must reset the timer.
But some owner controled function do not reset the time:

  • contractInteractions

  • createEstateNFT

  • removeBeneficiary

The inherit function relies on the deadline:

function inherit() external {
if (block.timestamp < getDeadline()) {
revert InactivityPeriodNotLongEnough();
}
if (beneficiaries.length == 1) {
owner = msg.sender;
_setDeadline();
} else if (beneficiaries.length > 1) {
isInherited = true;
} else {
revert InvalidBeneficiaries();
}
}

Exploit Scenario

  1. Setup: The owner performs an action that resets the deadline (e.g., sendETH), setting deadline = block.timestamp + 90 days.

  2. Owner Activity Without Reset: Over the next 89 days, the owner calls createEstateNFT, contractInteractions, or removeBeneficiary multiple times, managing the contract actively but not resetting the timer.

  3. Timer Expires: On day 90, despite recent activity (e.g., day 89 via contractInteractions), ` block.timestamp >= deadlinebecomes true because the last reset was on day 0.

  4. Exploitation:

    • Single Beneficiary: An attacker calls inherit, becoming the new owner since beneficiaries.length == 1, gaining control and resetting the deadline.

    • Multiple Beneficiaries: Any caller sets isInherited = true, allowing beneficiaries to call withdrawInheritedFunds and drain funds.

  5. Result: The attacker or beneficiaries exploit the owner’s active management (via non-resetting functions) to trigger inheritance prematurely.

Impact

The 90-day timer expires despite owner activity, allowing inheritance to occur earlier than intended, violating the invariant.

An attacker can take ownership (single beneficiary) or trigger fund withdrawal (multiple beneficiaries), bypassing the owner’s active management.

Tools Used

Manual code review

Recommendations

Ensure every owner-controlled function resets the deadline by adding _setDeadline() calls where missing

Updates

Lead Judging Commences

0xtimefliez Lead Judge 4 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.