The InheritanceManager contract is designed to facilitate asset inheritance by enforcing a 90-day inactivity period. If the owner does not interact with the contract within this timeframe, beneficiaries can claim the stored assets. A fundamental design assumption of the contract is that "every transaction the owner does with this contract must reset the 90-day timer." However, a critical flaw has been identified: when the owner deposits tokens (e.g., ERC20 tokens) into the contract via a direct transfer, the 90-day timer does not reset. This violates the contract’s core assumption and exposes it to the risk of premature inheritance claims, even when the owner has recently interacted with the contract.
The InheritanceManager contract relies on an internal mechanism to track owner activity, resetting a 90-day timer by updating a deadline variable through the _setDeadline() function. This function is typically invoked in owner-restricted methods such as addBeneficiary, sendERC20, and sendETH, ensuring that explicit owner actions reset the inactivity period.
However, a significant oversight exists when the owner deposits tokens directly into the contract using a standard ERC20 transfer function (e.g., IERC20(token).transfer(contractAddress, amount)). The behavior in this scenario is as follows:
Token Deposit: The ERC20 tokens are successfully transferred to the contract’s address, increasing its balance.
Timer Behavior: The 90-day timer is not reset because the direct transfer does not trigger any executable logic within the InheritanceManager contract. Specifically, the _setDeadline() function is not called, as no contract function is invoked during a direct transfer.
This failure to recognize a token deposit as an owner-initiated activity undermines the contract’s intended functionality.
To illustrate the flaw, consider the following timeline:
Contract Deployment: The owner deploys the contract and adds beneficiaries, triggering _setDeadline() and setting the initial deadline to block.timestamp + 90 days.
Token Deposit: 85 days later, the owner transfers ERC20 tokens directly to the contract address using transfer. The token balance increases, but the timer remains unchanged.
Inactivity Period Expires: 5 days later (90 days from the initial deadline), the original deadline is reached.
Inheritance Triggered: Beneficiaries call inherit() and claim the assets, despite the owner’s recent deposit activity.
In this case, the owner’s token deposit an intentional interaction with the contract does not extend the inactivity period, allowing beneficiaries to claim assets prematurely.
This flaw has significant consequences for the contract’s reliability and security:
Premature Inheritance Claims: Beneficiaries can claim assets shortly after an owner’s token deposit if the deposit occurs near the end of the 90-day period, as the timer does not reset. This contradicts the contract’s purpose of ensuring a full 90-day inactivity window.
User Expectation Misalignment: Owners reasonably assume that depositing tokens into the contract qualifies as an activity that resets the timer. The current behavior violates this expectation, potentially leading to confusion or disputes.
Compromised Contract Integrity: The inability to consistently track owner activity undermines the contract’s core mechanism, reducing its trustworthiness and exposing it to exploitation.
Manual Review
To resolve this flaw and ensure that all owner interactions, including token deposits, reset the 90-day timer, the following remediation steps are proposed:
Implement a Dedicated Deposit Function
Add a depositTokens function to handle token deposits explicitly and reset the timer. This function should:
Transfer tokens from the owner to the contract.
Call _setDeadline() to update the timer.
Example implementation:
Benefits: Provides a controlled method for token deposits, ensuring timer resets while maintaining security through the onlyOwner modifier. The use of safeTransferFrom (from OpenZeppelin’s SafeERC20 library) enhances robustness.
Update Documentation and User Instructions
Explicitly document that direct token transfers (e.g., transfer) do not reset the timer and instruct owners to use the depositTokens function instead. This reduces the risk of unintentional behavior due to user misunderstanding.
Optional: Support Token Hooks
For advanced token standards like ERC777, which include a tokensReceived hook, implement this interface to detect incoming tokens and reset the timer:
Limitation: This approach only applies to ERC777 tokens and is not a complete solution, as most tokens in use are ERC20-based. It can serve as a supplementary safeguard.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.