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

[H-2] The `InheritanceManager` contract cannot accept ETH

Summary

In Ethereum smart contracts, the ability to receive Ether (ETH) directly via transactions (e.g., from an externally owned account or another contract) requires the explicit implementation of a receive() or fallback() function. By default, a contract without these functions will reject any ETH sent to it, causing the transaction to revert. In the InheritanceManager contract, no such functions are defined, meaning it cannot accept ETH transfers despite its intended functionality as a wallet-like system that manages assets, including ETH.

Vulnerability Details

This limitation is particularly problematic because the contract includes a sendETH function, which allows the owner to transfer ETH out of the contract to a specified address. However, without a mechanism to receive ETH (e.g., via a direct transfer from a user or another contract), the contract can only send ETH that was already present at deployment or deposited through an alternative, indirect method (if any exists). This undermines the contract’s utility as a flexible inheritance management system, as users cannot easily fund it with ETH to support inheritance payouts or NFT buyouts. For example, an owner attempting to send ETH to the contract using a simple payable transfer (e.g., address(contract).call{value: 10 ether}("")) will see the transaction fail silently, with no clear indication of why unless they inspect the contract’s code.

The absence of ETH receivability also introduces a usability gap: beneficiaries or external systems expecting to interact with the contract by sending ETH (e.g., to pre-fund inheritance distributions) cannot do so, limiting the contract’s interoperability within the Ethereum ecosystem. This issue could lead to confusion or operational failures, especially if the contract’s documentation or UI implies ETH deposits are supported.

Likelihood: High. Any attempt to send ETH directly (common user behavior) will fail, making this a guaranteed issue in normal usage.

function test_cannotAcceptETH() public {
address user2 = makeAddr("user2");
vm.deal(address(user2), 10e18);
vm.startPrank(user2);
(bool s,) = payable(address(im)).call{value: 10e18}("");
vm.stopPrank();
assertFalse(s);
}

Impact

High. The contract is supposed to work with ETH as such function is InheritanceManager::sendETH. Without the ability to receive ETH, the contract’s functionality is severely restricted, potentially locking out a core asset type from its inheritance management capabilities.

Tools Used

  • Manual Review

Recommendations

Add payable keyword to constructor and a receive() function to allow the contract to accept ETH:

+constructor() payable {
owner = msg.sender;
nft = new NFTFactory(address(this));
}
+ receive() external payable {}
Updates

Lead Judging Commences

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

Missing receive() or fallback() function

Support

FAQs

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