账户
0x7a...a623
0x7A...A623

0x7A...A623

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.6.12+commit.27d51765
语言
Solidity
合同源代码
文件 1 的 7:Address.sol
合同源代码
文件 2 的 7:Context.sol
合同源代码
文件 3 的 7:IERC20.sol
合同源代码
文件 4 的 7:ReentrancyGuard.sol
合同源代码
文件 5 的 7:SafeERC20.sol
合同源代码
文件 6 的 7:SafeMath.sol
合同源代码
文件 7 的 7:TokenVesting.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/GSN/Context.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SafeMath.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/SafeERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuard.sol";


/**
 * @title TokenVesting
 * @dev A token holder contract that can release its token balance gradually like a
 * typical vesting scheme, with a cliff and vesting period. Optionally revocable by the
 * owner.
 */
contract TokenVesting is Context, ReentrancyGuard  {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    event Released(uint256 amount);

    IERC20 private _token;

    struct Vesting {
        uint256 start;
        uint256 interval;
        uint256 duration;
        uint256 balance;
        uint256 released;
    }

    mapping (address => Vesting) private _vestings;

    constructor (address token) public {
        require(token != address(0), "token address cannot be zero");
        _token = IERC20(token);
    }

    function getVesting(address beneficiary) public view returns (uint256, uint256, uint256, uint256, uint256) {
        Vesting memory v = _vestings[beneficiary];
        return (v.start, v.interval, v.duration, v.balance, v.released);
    }

    function createVesting(
        address beneficiary,
        uint256 start,
        uint256 interval,
        uint256 duration,
        uint256 amount
    ) external nonReentrant {
        require(interval > 0 , "TokenVesting #createVesting: interval must be greater than 0");
        require(duration >= interval, "TokenVesting #createVesting: interval cannot be bigger than duration");

        Vesting storage vest = _vestings[beneficiary];
        require(vest.balance == 0, "TokenVesting #createVesting: vesting for beneficiary already created");

        _token.safeTransferFrom(_msgSender(), address(this), amount);

        vest.start = start;
        vest.interval = interval;
        vest.duration = duration;
        vest.balance = amount;
        vest.released = uint256(0);
    }

    function postponeVesting(uint256 start) external {
        Vesting storage vest = _vestings[_msgSender()];
        require(vest.balance != 0, "TokenVesting #postponeVesting: vesting for beneficiary does not exist");
        require(vest.start < start, "TokenVesting #postponeVesting: new start date cannot be earlier than original start date");
        vest.start = start;
    }

    function release(address beneficiary) external nonReentrant {
        uint256 unreleased = releasableAmount(beneficiary);
        require(unreleased > 0, "TokenVesting #release: nothing to release");

        Vesting storage vest = _vestings[beneficiary];

        vest.released = vest.released.add(unreleased);
        vest.balance = vest.balance.sub(unreleased);

        _token.safeTransfer(beneficiary, unreleased);
        emit Released(unreleased);
    }

    function releasableAmount(address beneficiary) public view returns (uint256) {
        return vestedAmount(beneficiary).sub(_vestings[beneficiary].released);
    }

    function vestedAmount(address beneficiary) public view returns (uint256) {
        Vesting memory vest = _vestings[beneficiary];
        uint256 currentBalance = vest.balance;
        uint256 totalBalance = currentBalance.add(vest.released);

        if (block.timestamp >= vest.start.add(vest.duration)) {
            return totalBalance;
        } else {
            uint256 numberOfInvervals = block.timestamp.sub(vest.start).div(vest.interval);
            uint256 totalIntervals = vest.duration.div(vest.interval);
            return totalBalance.mul(numberOfInvervals).div(totalIntervals);
        }
    }
}
设置
{
  "compilationTarget": {
    "browser/TokenVesting.sol": "TokenVesting"
  },
  "evmVersion": "istanbul",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Released","type":"event"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"interval","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"createVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"}],"name":"getVesting","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"start","type":"uint256"}],"name":"postponeVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"}],"name":"releasableAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"}],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"}],"name":"vestedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]