Summary
All owner interactions should update the deadline at which we can consider the owner inactive. This is the case with InheritanceManager::sendERC20
and InheritanceManager::sendETH
.
Vulnerability Details
Some functions that DO NOT update the deadline are:
InheritanceManager::contractInteractions
InheritanceManager::createEstateNFT
InheritanceManager::removeBeneficiary
Likelihood: Medium. Depends on owner behavior (e.g., using contractInteractions as the last action) and beneficiaries noticing the deadline lapse.
function test_contractInteractionsDoesNotUpdateDeadline() public {
address user2 = makeAddr("user2");
usdc.mint(address(im), 10e18);
vm.startPrank(owner);
uint256 currentDeadline = im.getDeadline();
bytes memory payload = abi.encodeWithSignature("transfer(address,uint256)", user2, 1);
im.contractInteractions(address(usdc), payload, 0, true);
uint256 afterTransactionDeadline = im.getDeadline();
vm.stopPrank();
assertEq(currentDeadline, afterTransactionDeadline);
}
function test_createEstateNFTDoesNotUpdateDeadline() public {
address user2 = makeAddr("user2");
usdc.mint(address(im), 10e18);
vm.startPrank(owner);
uint256 currentDeadline = im.getDeadline();
im.createEstateNFT("Description", 1, address(usdc));
uint256 afterTransactionDeadline = im.getDeadline();
vm.stopPrank();
assertEq(currentDeadline, afterTransactionDeadline);
}
Impact
High as if contractInteractions
are the last type of transaction, the deadline will pass, allowing beneficiaries to withdraw funds from the wallet.
Tools Used
Recommendations
function contractInteractions(address _target, bytes calldata _payload, uint256 _value, bool _storeTarget)
external
nonReentrant
onlyOwner
{
(bool success, bytes memory data) = _target.call{value: _value}(_payload);
require(success, "interaction failed");
if (_storeTarget) {
interactions[_target] = data;
}
+ _setDeadline();
}