Forkchoice Ethereum Mainnet

Address Contract Partially Verified

Address 0xed0527fB909BbE5CE0CD3b80a556D3524500bfdc
Balance 0 ETH
Nonce 1
Code Size 7760 bytes
Indexed Transactions 0 (1 on-chain, 1.6% indexed)
External Etherscan · Sourcify

Contract Bytecode

7760 bytes
Copy Bytecode
0x6080604052600436106101985760003560e01c806385701c4d116100e0578063b1e1053311610084578063f2fde38b11610061578063f2fde38b14610514578063f51321d714610534578063f7c469f014610554578063f9079b37146105c957005b8063b1e105331461048e578063dd62ed3e146104ae578063ea1bb3d5146104f457005b806395d89b41116100bd57806395d89b41146104195780639ef346b41461042e578063a457c2d71461044e578063a9059cbb1461046e57005b806385701c4d1461036f5780638af104da1461038f5780638da5cb5b146103f157005b8063313ce567116101475780635a7bb69a116101245780635a7bb69a146102c157806370a08231146102f7578063715018a61461032d5780637e913dc61461034257005b8063313ce56714610270578063395093511461028c57806348deb471146102ac57005b806317e289e91161017557806317e289e91461021b57806318160ddd1461023b57806323b872dd1461025057005b806306fdde03146101a1578063095ea7b3146101cc57806313083617146101fc57005b3661019f57005b005b3480156101ad57600080fd5b506101b66105e9565b6040516101c39190611a58565b60405180910390f35b3480156101d857600080fd5b506101ec6101e7366004611ae7565b61067b565b60405190151581526020016101c3565b34801561020857600080fd5b506006545b6040519081526020016101c3565b34801561022757600080fd5b5061019f610236366004611b21565b610691565b34801561024757600080fd5b5060025461020d565b34801561025c57600080fd5b506101ec61026b366004611b84565b610ad6565b34801561027c57600080fd5b50604051601281526020016101c3565b34801561029857600080fd5b506101ec6102a7366004611ae7565b610b95565b3480156102b857600080fd5b5060085461020d565b3480156102cd57600080fd5b5061020d6102dc366004611bc0565b6001600160a01b031660009081526009602052604090205490565b34801561030357600080fd5b5061020d610312366004611bc0565b6001600160a01b031660009081526020819052604090205490565b34801561033957600080fd5b5061019f610bd1565b34801561034e57600080fd5b5061036261035d366004611bc0565b610c37565b6040516101c39190611bdb565b34801561037b57600080fd5b5061020d61038a366004611bc0565b610d6c565b34801561039b57600080fd5b5061020d6103aa366004611ae7565b6040516bffffffffffffffffffffffff19606084901b1660208201526034810182905260009060540160405160208183030381529060405280519060200120905092915050565b3480156103fd57600080fd5b506005546040516001600160a01b0390911681526020016101c3565b34801561042557600080fd5b506101b6610e27565b34801561043a57600080fd5b50610362610449366004611c66565b610e36565b34801561045a57600080fd5b506101ec610469366004611ae7565b610f3a565b34801561047a57600080fd5b506101ec610489366004611ae7565b610feb565b34801561049a57600080fd5b5061019f6104a9366004611c7f565b610ff8565b3480156104ba57600080fd5b5061020d6104c9366004611ce2565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b34801561050057600080fd5b5061020d61050f366004611c66565b611075565b34801561052057600080fd5b5061019f61052f366004611bc0565b6111e7565b34801561054057600080fd5b5061036261054f366004611ae7565b6112c9565b34801561056057600080fd5b5061020d61056f366004611bc0565b6001600160a01b0381166000908152600960209081526040808320548151606086901b6bffffffffffffffffffffffff19168185015260348082019290925282518082039092018252605401909152805191012092915050565b3480156105d557600080fd5b5061020d6105e4366004611c66565b61137e565b6060600380546105f890611d15565b80601f016020809104026020016040519081016040528092919081815260200182805461062490611d15565b80156106715780601f1061064657610100808354040283529160200191610671565b820191906000526020600020905b81548152906001019060200180831161065457829003601f168201915b5050505050905090565b6000610688338484611431565b50600192915050565b6005546001600160a01b031633146106f05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b600084116107405760405162461bcd60e51b815260206004820152601460248201527f6475726174696f6e206d757374206265203e203000000000000000000000000060448201526064016106e7565b600081116107905760405162461bcd60e51b815260206004820152601260248201527f616d6f756e74206d757374206265203e2030000000000000000000000000000060448201526064016106e7565b838511156107e05760405162461bcd60e51b815260206004820152600d60248201527f696e76616c696420636c6966660000000000000000000000000000000000000060448201526064016106e7565b60018310156108315760405162461bcd60e51b815260206004820152601f60248201527f736c696365506572696f645365636f6e6473206d757374206265203e3d20310060448201526064016106e7565b6040517ff7c469f00000000000000000000000000000000000000000000000000000000081526001600160a01b0388166004820152600090309063f7c469f090602401602060405180830381865afa158015610891573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b59190611d4a565b905060006108c3888861140d565b90506040518061014001604052806001151581526020018a6001600160a01b03168152602001828152602001898152602001878152602001868152602001851515815260200184815260200160008152602001600015158152506007600084815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010155606082015181600201556080820151816003015560a0820151816004015560c08201518160050160006101000a81548160ff02191690831515021790555060e0820151816006015561010082015181600701556101208201518160080160006101000a81548160ff021916908315150217905550905050610a138360085461140d90919063ffffffff16565b6008556006805460018181019092557ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f018390556001600160a01b038a1660009081526009602052604090205490610a6c90829061140d565b6001600160a01b038b166000818152600960209081526040918290209390935580518681529283019190915281018590527f9c550cbfc002e2d474c81a28bfec4830553d15cadbf57242afdc7510f2cb67149060600160405180910390a150505050505050505050565b6000610ae3848484611589565b6001600160a01b038416600090815260016020908152604080832033845290915290205482811015610b7d5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084016106e7565b610b8a8533858403611431565b506001949350505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610688918590610bcc908690611d79565b611431565b6005546001600160a01b03163314610c2b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e7565b610c3560006117ad565b565b610c9c60405180610140016040528060001515815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160001515815260200160008152602001600081526020016000151581525090565b6001600160a01b03821660009081526009602052604081205460079190610ccb9085906103aa90600190611d91565b81526020808201929092526040908101600020815161014081018352815460ff808216151583526001600160a01b036101009283900416958301959095526001830154938201939093526002820154606082015260038201546080820152600482015460a082015260058201548416151560c0820152600682015460e082015260078201549281019290925260080154909116151561012082015292915050565b6001600160a01b038116600090815260096020526040812054600654811115610dd75760405162461bcd60e51b815260206004820152601360248201527f696e646578206f7574206f6620626f756e64730000000000000000000000000060448201526064016106e7565b6000805b82811015610e1f576000610def86836112c9565b90506000610dfc82611817565b9050610e08848261140d565b935050508080610e1790611da8565b915050610ddb565b509392505050565b6060600480546105f890611d15565b610e9b60405180610140016040528060001515815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160001515815260200160008152602001600081526020016000151581525090565b50600090815260076020818152604092839020835161014081018552815460ff808216151583526001600160a01b036101009283900416948301949094526001830154958201959095526002820154606082015260038201546080820152600482015460a082015260058201548316151560c0820152600682015460e08201529281015493830193909352600890920154909116151561012082015290565b3360009081526001602090815260408083206001600160a01b038616845290915281205482811015610fd45760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106e7565b610fe13385858403611431565b5060019392505050565b6000610688338484611589565b6005546001600160a01b031633146110525760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e7565b6110618786868686868c610691565b61106b8787610feb565b5050505050505050565b600081815260076020526040812054829060ff1615156001146110da5760405162461bcd60e51b815260206004820152600e60248201527f6e6f7420696e7469616c697a656400000000000000000000000000000000000060448201526064016106e7565b60008181526007602052604090206008015460ff161561113c5760405162461bcd60e51b815260206004820152600f60248201527f616c7265616479207265766f6b6564000000000000000000000000000000000060448201526064016106e7565b600083815260076020818152604092839020835161014081018552815460ff808216151583526001600160a01b036101009283900416948301949094526001830154958201959095526002820154606082015260038201546080820152600482015460a082015260058201548316151560c0820152600682015460e0820152928101549383019390935260088301541615156101208201526111dd906118ee565b9250505b50919050565b6005546001600160a01b031633146112415760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e7565b6001600160a01b0381166112bd5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106e7565b6112c6816117ad565b50565b61132e60405180610140016040528060001515815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160001515815260200160008152602001600081526020016000151581525090565b60408051606085901b6bffffffffffffffffffffffff19166020808301919091526034808301869052835180840390910181526054909201909252805191012061137790610e36565b9392505050565b600061138960065490565b82106113d75760405162461bcd60e51b815260206004820152601360248201527f696e646578206f7574206f6620626f756e64730000000000000000000000000060448201526064016106e7565b600682815481106113ea576113ea611dc3565b90600052602060002001549050919050565b60006113778284611d91565b505050565b60006113778284611d79565b60006113778284611dd9565b60006113778284611dfb565b6001600160a01b0383166114ac5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106e7565b6001600160a01b0382166115285760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106e7565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166116055760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106e7565b6001600160a01b0382166116815760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106e7565b61168c8383836119bf565b6001600160a01b0383166000908152602081905260409020548181101561171b5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106e7565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290611752908490611d79565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161179e91815260200190565b60405180910390a35b50505050565b600580546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61012081015160009042901515600114156118355750600092915050565b826040015181101561184a57505060e0015190565b6080830151606084015161185d9161140d565b811061186c5750600092915050565b60006118858460600151836113fc90919063ffffffff16565b60a085015190915060006118998383611419565b905060006118a78284611425565b905060006118d088608001516118ca848b60e0015161142590919063ffffffff16565b90611419565b60e08901519091506118e290826113fc565b98975050505050505050565b6040810151600090429081108061190c575061012083015115156001145b1561191a5750600092915050565b6080830151606084015161192d9161140d565b81106119475761010083015160e0840151611377916113fc565b60006119608460600151836113fc90919063ffffffff16565b60a085015190915060006119748383611419565b905060006119828284611425565b905060006119a588608001516118ca848b60e0015161142590919063ffffffff16565b90506118e2886101000151826113fc90919063ffffffff16565b60006119ca84610d6c565b90506001600160a01b03841615611a5357611a04816119fe866001600160a01b031660009081526020819052604090205490565b906113fc565b821115611a535760405162461bcd60e51b815260206004820152601860248201527f636865636b2076657374696e67206f722062616c616e6365000000000000000060448201526064016106e7565b6117a7565b600060208083528351808285015260005b81811015611a8557858101830151858201604001528201611a69565b81811115611a97576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b80356001600160a01b0381168114611ae257600080fd5b919050565b60008060408385031215611afa57600080fd5b611b0383611acb565b946020939093013593505050565b80358015158114611ae257600080fd5b600080600080600080600060e0888a031215611b3c57600080fd5b611b4588611acb565b965060208801359550604088013594506060880135935060808801359250611b6f60a08901611b11565b915060c0880135905092959891949750929550565b600080600060608486031215611b9957600080fd5b611ba284611acb565b9250611bb060208501611acb565b9150604084013590509250925092565b600060208284031215611bd257600080fd5b61137782611acb565b81511515815261014081016020830151611c0060208401826001600160a01b03169052565b5060408301516040830152606083015160608301526080830151608083015260a083015160a083015260c0830151611c3c60c084018215159052565b5060e083810151908301526101008084015190830152610120928301511515929091019190915290565b600060208284031215611c7857600080fd5b5035919050565b600080600080600080600060e0888a031215611c9a57600080fd5b611ca388611acb565b96506020880135955060408801359450606088013593506080880135925060a08801359150611cd460c08901611b11565b905092959891949750929550565b60008060408385031215611cf557600080fd5b611cfe83611acb565b9150611d0c60208401611acb565b90509250929050565b600181811c90821680611d2957607f821691505b602082108114156111e157634e487b7160e01b600052602260045260246000fd5b600060208284031215611d5c57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115611d8c57611d8c611d63565b500190565b600082821015611da357611da3611d63565b500390565b6000600019821415611dbc57611dbc611d63565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600082611df657634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615611e1557611e15611d63565b50029056fea264697066735822122020d2276b9032f8308842431cbd6d7974842f3c1101e37025c94bf831f26bb91564736f6c634300080b0033

Verified Source Code Partial Match

Compiler: v0.8.11+commit.d7f03943 EVM: london Optimization: Yes (2000 runs)
Token.sol 580 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

pragma solidity ^0.8.0;

abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        _transferOwnership(_msgSender());
    }

    function owner() public view virtual returns (address) {
        return _owner;
    }

    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

pragma solidity ^0.8.0;

interface IERC20 {
    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

pragma solidity ^0.8.0;

interface IERC20Metadata is IERC20 {
    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);
}

pragma solidity ^0.8.0;

contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    function name() public view virtual override returns (string memory) {
        return _name;
    }

    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);
        }

        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(_msgSender(), spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

pragma solidity ^0.8.0;

library SafeMath {
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}
pragma solidity ^0.8.11;

contract Token is ERC20, Ownable {
    using SafeMath for uint256;
    
    struct VestingSchedule{
        bool initialized;
        address  beneficiary;
        uint256  cliff;
        uint256  start;
        uint256  duration;
        uint256 slicePeriodSeconds;
        bool  revocable;
        uint256 amountTotal;
        uint256  released;
        bool revoked;
    }

    bytes32[] private vestingSchedulesIds;
    mapping(bytes32 => VestingSchedule) private vestingSchedules;
    uint256 private vestingSchedulesTotalAmount;
    mapping(address => uint256) private holdersVestingCount;

    event Released(uint256 amount);
    event Revoked(bytes32);
    event VestingCreated(bytes32, address, uint256);

    modifier onlyIfVestingScheduleExists(bytes32 vestingScheduleId) {
        require(vestingSchedules[vestingScheduleId].initialized == true, "not intialized");
        _;
    }

    modifier onlyIfVestingScheduleNotRevoked(bytes32 vestingScheduleId) {
        require(vestingSchedules[vestingScheduleId].initialized == true, "not intialized");
        require(vestingSchedules[vestingScheduleId].revoked == false, "already revoked");
        _;
    }

    constructor(
        string memory name,
        string memory symbol,
        uint256 initialSupply
    ) ERC20(name, symbol) {
        _mint(msg.sender, initialSupply);
    }

    receive() external payable {}

    fallback() external payable {}

    function getVestingSchedulesCountByBeneficiary(address _beneficiary)
    public
    view
    returns(uint256){
        return holdersVestingCount[_beneficiary];
    }

    function getVestingIdAtIndex(uint256 index)
    external
    view
    returns(bytes32){
        require(index < getVestingSchedulesCount(), "index out of bounds");
        return vestingSchedulesIds[index];
    }

    function getVestingScheduleByAddressAndIndex(address holder, uint256 index)
    public
    view
    returns(VestingSchedule memory){
        return getVestingSchedule(computeVestingScheduleIdForAddressAndIndex(holder, index));
    }

    function getVestingSchedulesTotalAmount()
    external
    view
    returns(uint256){
        return vestingSchedulesTotalAmount;
    }

    function createVestingSchedule(
        address _beneficiary,
        uint256 _start,
        uint256 _cliff,
        uint256 _duration,
        uint256 _slicePeriodSeconds,
        bool _revocable,
        uint256 _amount
    ) onlyOwner() public {
        require(_duration > 0, "duration must be > 0");
        require(_amount > 0, "amount must be > 0");
        require(_cliff <= _duration, "invalid cliff");
        require(_slicePeriodSeconds >= 1, "slicePeriodSeconds must be >= 1");

        bytes32 vestingScheduleId = this.computeNextVestingScheduleIdForHolder(_beneficiary);
        uint256 cliff = _start.add(_cliff);
        vestingSchedules[vestingScheduleId] = VestingSchedule(
            true,
            _beneficiary,
            cliff,
            _start,
            _duration,
            _slicePeriodSeconds,
            _revocable,
            _amount,
            0,
            false
        );
        vestingSchedulesTotalAmount = vestingSchedulesTotalAmount.add(_amount);
        vestingSchedulesIds.push(vestingScheduleId);
        uint256 currentVestingCount = holdersVestingCount[_beneficiary];
        holdersVestingCount[_beneficiary] = currentVestingCount.add(1);

        emit VestingCreated(vestingScheduleId, _beneficiary, _amount);
    }

    function getVestingSchedulesCount()
        public
        view
        returns(uint256){
        return vestingSchedulesIds.length;
    }

    function computeReleasableAmount(bytes32 vestingScheduleId)
        public
        onlyIfVestingScheduleNotRevoked(vestingScheduleId)
        view
        returns(uint256){
        VestingSchedule storage vestingSchedule = vestingSchedules[vestingScheduleId];
        return _computeReleasableAmount(vestingSchedule);
    }

    function computeLockedAmount(address holder)
        public
        view
        returns(uint256) {
        uint count = getVestingSchedulesCountByBeneficiary(holder);
        require(count <= getVestingSchedulesCount(), "index out of bounds");
        uint totalLocked = 0;
        for (uint i = 0; i < count; i++) {
            VestingSchedule memory vestingSchedule = getVestingScheduleByAddressAndIndex(holder, i);
            
            uint256 lockedAmount = _computeLockedAmount(vestingSchedule);
            totalLocked = totalLocked.add(lockedAmount);
        }

        return totalLocked;
    }

    function getVestingSchedule(bytes32 vestingScheduleId)
        public
        view
        returns(VestingSchedule memory){
        return vestingSchedules[vestingScheduleId];
    }

    function computeNextVestingScheduleIdForHolder(address holder)
        public
        view
        returns(bytes32){
        return computeVestingScheduleIdForAddressAndIndex(holder, holdersVestingCount[holder]);
    }

    function getLastVestingScheduleForHolder(address holder)
        public
        view
        returns(VestingSchedule memory){
        return vestingSchedules[computeVestingScheduleIdForAddressAndIndex(holder, holdersVestingCount[holder] - 1)];
    }

    function computeVestingScheduleIdForAddressAndIndex(address holder, uint256 index)
        public
        pure
        returns(bytes32){
        return keccak256(abi.encodePacked(holder, index));
    }

    function _computeReleasableAmount(VestingSchedule memory vestingSchedule)
    internal
    view
    returns(uint256){
        uint256 currentTime = getCurrentTime();
        if ((currentTime < vestingSchedule.cliff) || vestingSchedule.revoked == true) {
            return 0;
        } else if (currentTime >= vestingSchedule.start.add(vestingSchedule.duration)) {
            return vestingSchedule.amountTotal.sub(vestingSchedule.released);
        } else {
            uint256 timeFromStart = currentTime.sub(vestingSchedule.start);
            uint secondsPerSlice = vestingSchedule.slicePeriodSeconds;
            uint256 vestedSlicePeriods = timeFromStart.div(secondsPerSlice);
            uint256 vestedSeconds = vestedSlicePeriods.mul(secondsPerSlice);
            uint256 vestedAmount = vestingSchedule.amountTotal.mul(vestedSeconds).div(vestingSchedule.duration);
            vestedAmount = vestedAmount.sub(vestingSchedule.released);
            return vestedAmount;
        }
    }

    function _computeLockedAmount(VestingSchedule memory vestingSchedule)
    internal
    view
    returns(uint256){
        uint256 currentTime = getCurrentTime();
        if (vestingSchedule.revoked == true) {
            return 0;
        } else if ((currentTime < vestingSchedule.cliff)) {
            return vestingSchedule.amountTotal;
        } else if (currentTime >= vestingSchedule.start.add(vestingSchedule.duration)) {
            return 0;
        } else {
            uint256 timeFromStart = currentTime.sub(vestingSchedule.start);
            uint secondsPerSlice = vestingSchedule.slicePeriodSeconds;
            uint256 vestedSlicePeriods = timeFromStart.div(secondsPerSlice);
            uint256 vestedSeconds = vestedSlicePeriods.mul(secondsPerSlice);
            uint256 vestedAmount = vestingSchedule.amountTotal.mul(vestedSeconds).div(vestingSchedule.duration);
            return vestingSchedule.amountTotal.sub(vestedAmount);
        }
    }

    function getCurrentTime()
        internal
        virtual
        view
        returns(uint256){
        return block.timestamp;
    }

    function _beforeTokenTransfer(address from, address to, uint256 amount) internal override virtual {
        uint totalLocked = computeLockedAmount(from);
        
        if (from != address(0)) require(amount <= balanceOf(from).sub(totalLocked), 'check vesting or balance');
        super._beforeTokenTransfer(from, to, amount);
    }

    function vestedTransfer(
        address _recipient, 
        uint256 _amount, 
        uint256 _start, 
        uint256 _cliff, 
        uint256 _duration, 
        uint256 _slicePeriodSeconds, 
        bool _revocable
    ) onlyOwner() public virtual {
        createVestingSchedule(_recipient, _start, _cliff, _duration, _slicePeriodSeconds, _revocable, _amount);
        super.transfer(_recipient, _amount);
    }
}

Read Contract

allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
computeLockedAmount 0x85701c4d → uint256
computeNextVestingScheduleIdForHolder 0xf7c469f0 → bytes32
computeReleasableAmount 0xea1bb3d5 → uint256
computeVestingScheduleIdForAddressAndIndex 0x8af104da → bytes32
decimals 0x313ce567 → uint8
getLastVestingScheduleForHolder 0x7e913dc6 → tuple
getVestingIdAtIndex 0xf9079b37 → bytes32
getVestingSchedule 0x9ef346b4 → tuple
getVestingScheduleByAddressAndIndex 0xf51321d7 → tuple
getVestingSchedulesCount 0x13083617 → uint256
getVestingSchedulesCountByBeneficiary 0x5a7bb69a → uint256
getVestingSchedulesTotalAmount 0x48deb471 → uint256
name 0x06fdde03 → string
owner 0x8da5cb5b → address
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256

Write Contract 9 functions

These functions modify contract state and require a wallet transaction to execute.

approve 0x095ea7b3
address spender
uint256 amount
returns: bool
createVestingSchedule 0x17e289e9
address _beneficiary
uint256 _start
uint256 _cliff
uint256 _duration
uint256 _slicePeriodSeconds
bool _revocable
uint256 _amount
decreaseAllowance 0xa457c2d7
address spender
uint256 subtractedValue
returns: bool
increaseAllowance 0x39509351
address spender
uint256 addedValue
returns: bool
renounceOwnership 0x715018a6
No parameters
transfer 0xa9059cbb
address recipient
uint256 amount
returns: bool
transferFrom 0x23b872dd
address sender
address recipient
uint256 amount
returns: bool
transferOwnership 0xf2fde38b
address newOwner
vestedTransfer 0xb1e10533
address _recipient
uint256 _amount
uint256 _start
uint256 _cliff
uint256 _duration
uint256 _slicePeriodSeconds
bool _revocable

Recent Transactions

This address has 1 on-chain transactions, but only 1.6% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →