Solidity Openzeppelin VestingWalletContract

Solidity Openzeppelin VestingWalletContract


foreword

The VestingWallet contract is used to issue eth or erc20 tokens to a certain user address within a period of time. The release method defaults to linear release, and supports rewriting the custom release method.

1. Interface

FUNCTIONS
constructor(beneficiaryAddress, startTimestamp, durationSeconds)

receive()

beneficiary()

start()

duration()

released()

released(token)

release()

release(token)

vestedAmount(timestamp)

vestedAmount(token, timestamp)

_vestingSchedule(totalAllocation, timestamp)

EVENTS
EtherReleased(amount)

ERC20Released(token, amount)

2. Openzeppelin implementation and annotations

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (finance/VestingWallet.sol)
pragma solidity ^0.8.0;

import "../token/ERC20/utils/SafeERC20.sol";
import "../utils/Address.sol";
import "../utils/Context.sol";

/**
 * @title VestingWallet
 * @dev This contract handles the vesting of Eth and ERC20 tokens for a given beneficiary. Custody of multiple tokens
 * can be given to this contract, which will release the token to the beneficiary following a given vesting schedule.
 * The vesting schedule is customizable through the {vestedAmount} function.
 *
 * Any token transferred to this contract will follow the vesting schedule as if they were locked from the beginning.
 * Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly)
 * be immediately releasable.
 */
contract VestingWallet is Context {
    
    
    event EtherReleased(uint256 amount);
    event ERC20Released(address indexed token, uint256 amount);

    uint256 private _released; //已释放的eth数量
    mapping(address => uint256) private _erc20Released;//已释放的erc20代币数量
    address private immutable _beneficiary;//被发放地址
    uint64 private immutable _start;//发放开始时间
    uint64 private immutable _duration;//发放时间间隔

    /**构建函数时需要传入发放地址,开始时间及发放间隔
     * @dev Set the beneficiary, start timestamp and vesting duration of the vesting wallet.
     */
    constructor(
        address beneficiaryAddress,
        uint64 startTimestamp,
        uint64 durationSeconds
    ) payable {
    
    
        require(beneficiaryAddress != address(0), "VestingWallet: beneficiary is zero address");
        _beneficiary = beneficiaryAddress;
        _start = startTimestamp;
        _duration = durationSeconds;
    }

    /**
     * @dev The contract should be able to receive Eth.
     */
    receive() external payable virtual {
    
    }

    /**
     * @dev Getter for the beneficiary address.
     */
    function beneficiary() public view virtual returns (address) {
    
    
        return _beneficiary;
    }

    /**
     * @dev Getter for the start timestamp.
     */
    function start() public view virtual returns (uint256) {
    
    
        return _start;
    }

    /**
     * @dev Getter for the vesting duration.
     */
    function duration() public view virtual returns (uint256) {
    
    
        return _duration;
    }

    /**已释放数量
     * @dev Amount of eth already released
     */
    function released() public view virtual returns (uint256) {
    
    
        return _released;
    }

    /**
     * @dev Amount of token already released
     */
    function released(address token) public view virtual returns (uint256) {
    
    
        return _erc20Released[token];
    }

    /**剩余可释放数量
     * @dev Getter for the amount of releasable eth.
     */
    function releasable() public view virtual returns (uint256) {
    
    
        return vestedAmount(uint64(block.timestamp)) - released();
    }

    /**
     * @dev Getter for the amount of releasable `token` tokens. `token` should be the address of an
     * IERC20 contract.
     */
    function releasable(address token) public view virtual returns (uint256) {
    
    
        return vestedAmount(token, uint64(block.timestamp)) - released(token);
    }

    /**将当前可释放的eth份额发放给用户
     * @dev Release the native token (ether) that have already vested.
     *
     * Emits a {EtherReleased} event.
     */
    function release() public virtual {
    
    
        uint256 amount = releasable();
        _released += amount;
        emit EtherReleased(amount);
        Address.sendValue(payable(beneficiary()), amount);
    }

    /**将当前可释放的erc20份额发放给用户
     * @dev Release the tokens that have already vested.
     *
     * Emits a {ERC20Released} event.
     */
    function release(address token) public virtual {
    
    
        uint256 amount = releasable(token);
        _erc20Released[token] += amount;
        emit ERC20Released(token, amount);
        SafeERC20.safeTransfer(IERC20(token), beneficiary(), amount);
    }

    /**已发放的eth份额
     * @dev Calculates the amount of ether that has already vested. Default implementation is a linear vesting curve.
     */
    function vestedAmount(uint64 timestamp) public view virtual returns (uint256) {
    
    
        return _vestingSchedule(address(this).balance + released(), timestamp);
    }

    /**已发放的erc20份额
     * @dev Calculates the amount of tokens that has already vested. Default implementation is a linear vesting curve.
     */
    function vestedAmount(address token, uint64 timestamp) public view virtual returns (uint256) {
    
    
        return _vestingSchedule(IERC20(token).balanceOf(address(this)) + released(token), timestamp);
    }

    /**释放计划,默认线性释放
     * @dev Virtual implementation of the vesting formula. This returns the amount vested, as a function of time, for
     * an asset given its total historical allocation.
     */
    function _vestingSchedule(uint256 totalAllocation, uint64 timestamp) internal view virtual returns (uint256) {
    
    
        if (timestamp < start()) {
    
    
            return 0;
        } else if (timestamp > start() + duration()) {
    
    
            return totalAllocation;
        } else {
    
    
            return (totalAllocation * (timestamp - start())) / duration();
        }
    }
}

Guess you like

Origin blog.csdn.net/hhhhhhhhhjx/article/details/127304804