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 {}
}