The Digital Inheritance Problem
Cryptocurrency is famous for the phrase "not your keys, not your coins." However, this self-sovereignty creates a massive risk: if you pass away or lose access to your keys, your assets are effectively burned, locked forever in the blockchain. Traditional wills require lawyers and centralized execution. In the world of Web3, we can solve this with a Dead Man's Switch.
A Dead Man's Switch is a smart contract designed to transfer funds to a pre-defined backup address (an heir) if the original owner fails to interact with the contract for a specific period. It is a simple, trustless way to ensure your digital legacy isn't lost to the void.
The Logic of the Switch
The contract logic relies on three main components:
- The Owner: The person who currently controls the funds.
- The Heir: The designated recipient of the funds if the owner becomes inactive.
- The Heartbeat: A timestamp that is updated every time the owner interacts with the contract.
If the difference between the current time and the last heartbeat exceeds a certain threshold (e.g., one year), the heir gains the right to withdraw the balance.
The Implementation
Below is a clean, modern Solidity implementation of this pattern. We use block.timestamp to track time. While miners can manipulate timestamps slightly, the drift is negligible over long periods like months or years.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract DeadMansSwitch {
address public owner;
address public heir;
uint256 public lastCheckIn;
uint256 public constant TIMEOUT = 365 days;
event Heartbeat(uint256 timestamp);
event AssetsClaimed(address indexed heir, uint256 amount);
constructor(address _heir) payable {
require(_heir != address(0), "Heir cannot be zero address");
owner = msg.sender;
heir = _heir;
lastCheckIn = block.timestamp;
}
modifier onlyOwner() {
require(msg.sender == owner, "Only the owner can call this");
_;
}
// The owner calls this periodically to reset the timer
function ping() external onlyOwner {
lastCheckIn = block.timestamp;
emit Heartbeat(block.timestamp);
}
// The heir calls this if the owner has been inactive too long
function claim() external {
require(msg.sender == heir, "Only the designated heir can claim");
require(
block.timestamp > lastCheckIn + TIMEOUT,
"The owner is still active"
);
uint256 balance = address(this).balance;
payable(heir).transfer(balance);
emit AssetsClaimed(heir, balance);
}
// Allow the owner to change the heir if needed
function updateHeir(address _newHeir) external onlyOwner {
require(_newHeir != address(0), "New heir cannot be zero address");
heir = _newHeir;
}
// Accept additional funds
receive() external payable {}
}
Key Considerations
When deploying a Dead Man's Switch, you must consider operational security. If you lose your keys, you cannot "ping" the contract, and your heir will eventually be able to claim the funds. This is actually the intended behavior. However, you must ensure that your heir knows the contract exists and has the technical ability to call the claim() function.
Another factor is gas efficiency. By using a simple uint256 for the timestamp and a receive() function, the contract remains extremely cheap to maintain. The only cost is the occasional transaction fee for the ping() function, which you might trigger once every few months while performing other on-chain activities.
This pattern demonstrates the true power of Solidity: replacing complex legal intermediaries with a few lines of immutable, transparent code.
