Emergency Fund Release Contract

What it does:
A smart contract that securely locks emergency funds and releases them automatically or manually when predefined emergency conditions are met.

Why it matters:
In real-life emergencies, access to funds can be delayed by banks, paperwork, or human approval. This contract ensures fast, rule-based access to critical funds while preventing misuse during normal times.

How it works:

  • A user deposits funds into an emergency vault.

  • Emergency conditions are defined (time-lock, guardian approval, or inactivity).

  • Funds can be released instantly when an emergency trigger is activated.

  • Optional guardians can approve or veto a release.

  • All actions are recorded transparently on-chain.

      // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title EmergencyFundRelease
 * @author Nam
 * @notice Secure emergency fund vault with guardian-based release
 */
contract EmergencyFundRelease {

    address public owner;
    address[] public guardians;

    uint256 public emergencyBalance;
    uint256 public lastActivity;
    uint256 public inactivityPeriod;

    uint256 public approvalsRequired;
    bool public emergencyActive;

    mapping(address => bool) public isGuardian;
    mapping(address => bool) public approved;

    // -------------------- EVENTS --------------------

    event Deposited(address indexed from, uint256 amount);
    event EmergencyTriggered(address indexed by);
    event Approved(address indexed guardian);
    event FundsReleased(address indexed to, uint256 amount);

    // -------------------- MODIFIERS --------------------

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    modifier onlyGuardian() {
        require(isGuardian[msg.sender], "Not guardian");
        _;
    }

    // -------------------- CONSTRUCTOR --------------------

    constructor(
        address[] memory _guardians,
        uint256 _approvalsRequired,
        uint256 _inactivityPeriod
    ) {
        require(_guardians.length >= _approvalsRequired, "Invalid guardians");
        require(_approvalsRequired > 0, "Approvals must be > 0");

        owner = msg.sender;
        inactivityPeriod = _inactivityPeriod;
        approvalsRequired = _approvalsRequired;

        for (uint256 i = 0; i  0, "No ETH sent");

        emergencyBalance += msg.value;
        lastActivity = block.timestamp;

        emit Deposited(msg.sender, msg.value);
    }

    /**
     * @notice Owner manually triggers emergency
     */
    function triggerEmergency() external onlyOwner {
        emergencyActive = true;
        emit EmergencyTriggered(msg.sender);
    }

    /**
     * @notice Auto-trigger emergency due to inactivity
     */
    function triggerByInactivity() external {
        require(
            block.timestamp >= lastActivity + inactivityPeriod,
            "Owner still active"
        );

        emergencyActive = true;
        emit EmergencyTriggered(msg.sender);
    }

    /**
     * @notice Guardian approves emergency fund release
     */
    function approveRelease() external onlyGuardian {
        require(emergencyActive, "Emergency not active");
        require(!approved[msg.sender], "Already approved");

        approved[msg.sender] = true;
        emit Approved(msg.sender);
    }

    /**
     * @notice Release funds when enough approvals are collected
     */
    function releaseFunds(address payable _to) external {
        require(emergencyActive, "Emergency not active");

        uint256 approvalCount;
        for (uint256 i = 0; i = approvalsRequired,
            "Not enough approvals"
        );

        uint256 amount = emergencyBalance;
        emergencyBalance = 0;
        emergencyActive = false;

        _to.transfer(amount);

        emit FundsReleased(_to, amount);
    }

    // -------------------- VIEW FUNCTIONS --------------------

    /**
     * @notice Check number of guardian approvals
     */
    function approvalStatus() external view returns (uint256 count) {
        for (uint256 i = 0; i < guardians.length; i++) {
            if (approved[guardians[i]]) {
                count++;
            }
        }
    }

    /**
     * @notice Get guardian list
     */
    function getGuardians() external view returns (address[] memory) {
        return guardians;
    }
}