Smart Will & Testament
What it does:
Automates the creation, storage, and execution of wills, ensuring assets are distributed according to the testator’s wishes without intermediaries.
Why it matters:
Reduces legal disputes, prevents asset loss, ensures enforceable distribution, and provides transparent and auditable inheritance management.
How it works:
-
Testator registers will details, beneficiaries, and asset allocation on-chain
-
Smart contract stores and locks assets securely until triggering conditions are met (e.g., proof of death)
-
Executors oracles can trigger will execution once conditions are verified
-
Assets are automatically distributed to beneficiaries according to predefined shares
-
Updates and amendments are tracked immutably
-
Integrates with tokenized assets, NFTs, and crypto wallets
-
Dashboards allow testators and executors to monitor status, pending distributions, and confirmations
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title SmartWill
* @author Nam
* @notice Manages wills, beneficiaries, and automated inheritance distribution on-chain
*/
contract SmartWill is Ownable {
struct Beneficiary {
address payable recipient;
uint256 share; // in percentage points (sum must be 100)
bool paid;
}
struct Will {
address testator;
uint256 totalAssets;
bool executed;
Beneficiary[] beneficiaries;
}
mapping(uint256 => Will) public wills;
uint256 public willCount;
mapping(address => bool) public authorizedOracles;
// -------------------- EVENTS --------------------
event OracleApproved(address oracle);
event OracleRevoked(address oracle);
event WillCreated(uint256 indexed willId, address testator);
event WillExecuted(uint256 indexed willId);
// -------------------- ORACLE MANAGEMENT --------------------
function approveOracle(address _oracle) external onlyOwner {
authorizedOracles[_oracle] = true;
emit OracleApproved(_oracle);
}
function revokeOracle(address _oracle) external onlyOwner {
authorizedOracles[_oracle] = false;
emit OracleRevoked(_oracle);
}
modifier onlyOracle() {
require(authorizedOracles[msg.sender], "Not an authorized oracle");
_;
}
// -------------------- WILL MANAGEMENT --------------------
function createWill(address[] calldata _beneficiaries, uint256[] calldata _shares) external payable {
require(_beneficiaries.length == _shares.length, "Mismatched beneficiaries and shares");
uint256 sumShares = 0;
for (uint256 i = 0; i < _shares.length; i++) {
sumShares += _shares[i];
}
require(sumShares == 100, "Total shares must be 100");
willCount += 1;
Will storage w = wills[willCount];
w.testator = msg.sender;
w.totalAssets = msg.value;
w.executed = false;
for (uint256 i = 0; i < _beneficiaries.length; i++) {
w.beneficiaries.push(Beneficiary({
recipient: payable(_beneficiaries[i]),
share: _shares[i],
paid: false
}));
}
emit WillCreated(willCount, msg.sender);
}
// -------------------- WILL EXECUTION --------------------
function executeWill(uint256 _willId) external onlyOracle {
Will storage w = wills[_willId];
require(!w.executed, "Will already executed");
for (uint256 i = 0; i < w.beneficiaries.length; i++) {
Beneficiary storage b = w.beneficiaries[i];
uint256 amount = (w.totalAssets * b.share) / 100;
b.recipient.transfer(amount);
b.paid = true;
}
w.executed = true;
emit WillExecuted(_willId);
}
// -------------------- VIEW FUNCTIONS --------------------
function getBeneficiaries(uint256 _willId) external view returns (Beneficiary[] memory) {
return wills[_willId].beneficiaries;
}
function isWillExecuted(uint256 _willId) external view returns (bool) {
return wills[_willId].executed;
}
// -------------------- FUNDING --------------------
receive() external payable {}
}