ERC20TimelockEitherBeneficiary

Description:

ERC20 token contract with Factory capabilities. Standard implementation for fungible tokens on Ethereum.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "ERC20TimelockEitherBeneficiary_3min.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 value) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

library SafeERC20 {
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 op failed");
        }
    }
}

/**
 * @title ERC20TimelockEitherBeneficiary
 * @notice Locks ERC20 tokens for 3 minutes from deployment. After release time,
 *         EITHER beneficiaryA or beneficiaryB can withdraw ALL tokens to themselves.
 *         Anyone can deposit via the owner-controlled fund() function (requires allowance).
 */
contract ERC20TimelockEitherBeneficiary {
    using SafeERC20 for IERC20;

    IERC20  public immutable token;
    address public immutable owner;
    address public immutable beneficiaryA;
    address public immutable beneficiaryB;
    uint64  public immutable releaseTime; // deploy + 3 minutes

    event Funded(address indexed from, uint256 amount);
    event Released(address indexed to, uint256 amount);

    error NotOwner();
    error NotBeneficiary();
    error NotYetReleased();
    error ZeroAmount();

    constructor(IERC20 _token, address _beneficiaryA, address _beneficiaryB) {
        require(address(_token) != address(0), "token=0");
        require(_beneficiaryA != address(0), "beneficiaryA=0");
        require(_beneficiaryB != address(0), "beneficiaryB=0");
        require(_beneficiaryA != _beneficiaryB, "beneficiaries must differ");

        token = _token;
        owner = msg.sender;
        beneficiaryA = _beneficiaryA;
        beneficiaryB = _beneficiaryB;
        releaseTime = uint64(block.timestamp + 3 minutes); // 部署后3分钟解锁
    }

    // Owner funds the contract with amount of tokens. Requires prior approve(owner -> this, amount).
    function fund(uint256 amount) external {
        if (msg.sender != owner) revert NotOwner();
        if (amount == 0) revert ZeroAmount();
        token.safeTransferFrom(msg.sender, address(this), amount);
        emit Funded(msg.sender, amount);
    }

    function balance() public view returns (uint256) {
        return token.balanceOf(address(this));
    }

    // Either beneficiary can withdraw ALL tokens to themselves once time passes.
    function release() external {
        if (block.timestamp < releaseTime) revert NotYetReleased();
        if (msg.sender != beneficiaryA && msg.sender != beneficiaryB) revert NotBeneficiary();

        uint256 amt = token.balanceOf(address(this));
        require(amt > 0, "nothing to release");

        token.safeTransfer(msg.sender, amt);
        emit Released(msg.sender, amt);
    }

    // (Optional convenience) Anyone can trigger a view to see time left.
    function timeLeft() external view returns (uint256) {
        if (block.timestamp >= releaseTime) return 0;
        return uint256(releaseTime) - block.timestamp;
    }
}
"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "remappings": []
  }
}}

Tags:
ERC20, Token, Factory|addr:0x284e705cd5474d86a13ed9f1ab1a6813b343357b|verified:true|block:23729512|tx:0xb78f1aa844286c01606e4dd7d8a1490f44e2e5e48b05d683ad64995f2b08411c|first_check:1762339459

Submitted on: 2025-11-05 11:44:21

Comments

Log in to comment.

No comments yet.