Free Token Vesting Wallet Smart Contract Template (Solidity)

Free Token Vesting Wallet Smart Contract Template (Solidity)

DevTools Store

Free Token Vesting Wallet Template (Solidity)

Linear/cliff vesting for team tokens, investor allocations.

pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract VestingWallet is Ownable {
    IERC20 public token;
    struct VestingSchedule {
        address beneficiary;
        uint256 totalAmount;
        uint256 released;
        uint256 start;
        uint256 cliffDuration;
        uint256 vestingDuration;
    }
    mapping(bytes32 => VestingSchedule) public schedules;

    constructor(address _token) Ownable(msg.sender) {
        token = IERC20(_token);
    }

    function createSchedule(
        address beneficiary, uint256 amount,
        uint256 start, uint256 cliff, uint256 duration
    ) external onlyOwner returns (bytes32) {
        bytes32 id = keccak256(abi.encodePacked(beneficiary, block.timestamp));
        schedules[id] = VestingSchedule(beneficiary, amount, 0, start, cliff, duration);
        token.transferFrom(msg.sender, address(this), amount);
        return id;
    }

    function release(bytes32 id) external {
        VestingSchedule storage s = schedules[id];
        uint256 vested = _vestedAmount(id);
        uint256 releasable = vested - s.released;
        require(releasable > 0);
        s.released += releasable;
        token.transfer(s.beneficiary, releasable);
    }

    function _vestedAmount(bytes32 id) internal view returns (uint256) {
        VestingSchedule storage s = schedules[id];
        if (block.timestamp < s.start + s.cliffDuration) return 0;
        if (block.timestamp >= s.start + s.vestingDuration) return s.totalAmount;
        return (s.totalAmount * (block.timestamp - s.start)) / s.vestingDuration;
    }
}

Full vesting with revocation, multiple schedules, deploy scripts, tests: https://rentry.co/w9gngnqt ($1+)

Report Page