Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0x6D7cb07A7615Bf192dBd8D1c80A9186d6b8ECBa6
Balance 0 ETH
Nonce 1
Code Size 6216 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

6216 bytes
0x608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80638eab5d0011610088578063a87430ba11610063578063a87430ba146101c8578063ca2324eb14610235578063f2fde38b14610248578063fc0c546a1461025b575f80fd5b80638eab5d001461018257806395aa6d2d14610195578063a583024b146101b5575f80fd5b80636ed93dd0116100c35780636ed93dd0146101195780637130b0eb1461013f578063715018a6146101565780638da5cb5b1461015e575f80fd5b806321888989146100e957806345a5405b146100fe5780634e71d92d14610111575b5f80fd5b6100fc6100f736600461121b565b61026e565b005b6100fc61010c366004611274565b61030b565b6100fc61077f565b610123620f424081565b60405165ffffffffffff90911681526020015b60405180910390f35b61014860025481565b604051908152602001610136565b6100fc610995565b5f546001600160a01b03165b6040516001600160a01b039091168152602001610136565b6100fc61019036600461130c565b6109a8565b6101a86101a33660046113b2565b610c95565b604051610136919061140b565b6101486101c3366004611479565b610df3565b6102086101d6366004611479565b60036020525f90815260409020546001600160781b038082169161ffff600160781b82041691600160881b9091041683565b604080516001600160781b03948516815261ffff9093166020840152921691810191909152606001610136565b6101236102433660046113b2565b610fe7565b6100fc610256366004611479565b611055565b60015461016a906001600160a01b031681565b610276611092565b5f5b818110156102cd5760035f84848481811061029557610295611499565b90506020020160208101906102aa9190611479565b6001600160a01b0316815260208101919091526040015f90812055600101610278565b507f67774df6a2db972a459b75a081f5c7358b131f3a3b5902418ed1353cbb588f7282826040516102ff9291906114e7565b60405180910390a15050565b610313611092565b65ffffffffffff86161561041e5782156103745760405162461bcd60e51b815260206004820152601a60248201527f756e6c6f636b54696d657374616d7073206e6f7420656d70747900000000000060448201526064015b60405180910390fd5b80156103c25760405162461bcd60e51b815260206004820152601b60248201527f756e6c6f636b50657263656e7461676573206e6f7420656d7074790000000000604482015260640161036b565b8565ffffffffffff168565ffffffffffff16116104195760405162461bcd60e51b81526020600482015260156024820152740656e64203e2073746172742074696d657374616d7605c1b604482015260640161036b565b6105ff565b65ffffffffffff8516156104745760405162461bcd60e51b815260206004820152601960248201527f6c696e65617256657374696e67456e64206e6f74207a65726f00000000000000604482015260640161036b565b8281146104935760405162461bcd60e51b815260040161036b906114fa565b60015b8381101561055b5784846104ab600184611545565b8181106104ba576104ba611499565b90506020020160208101906104cf919061155e565b65ffffffffffff168585838181106104e9576104e9611499565b90506020020160208101906104fe919061155e565b65ffffffffffff16116105535760405162461bcd60e51b815260206004820152601860248201527f696e76616c696420756e6c6f636b54696d657374616d70730000000000000000604482015260640161036b565b600101610496565b505f805b828110156105a25783838281811061057957610579611499565b905060200201602081019061058e919061155e565b6105989083611577565b915060010161055f565b5065ffffffffffff8116620f4240146105fd5760405162461bcd60e51b815260206004820152601e60248201527f756e6c6f636b50657263656e74616765732073756d206e6f7420313030250000604482015260640161036b565b505b60405180608001604052808765ffffffffffff1681526020018665ffffffffffff1681526020018585808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525050509082525060408051602085810282810182019093528582529283019290918691869182918501908490808284375f920182905250939094525050600280546004935090826106a48361159d565b90915550815260208082019290925260409081015f20835181548585015165ffffffffffff908116600160301b026bffffffffffffffffffffffff1990921692169190911717815590830151805191926107069260018501929091019061110d565b506060820151805161072291600284019160209091019061110d565b509050507f04669e2cbd2cc00f70508f0901a1cdc3b91c2127c6e042c3398c035c180ae18760016002546107569190611545565b87878787878760405161076f97969594939291906115ee565b60405180910390a1505050505050565b335f90815260036020526040812080549091906107a690600160781b900461ffff16610fe7565b82549091506001600160781b03166107f25760405162461bcd60e51b815260206004820152600f60248201526e1b9bdd081dda1a5d195b1a5cdd1959608a1b604482015260640161036b565b8065ffffffffffff16421161083f5760405162461bcd60e51b81526020600482015260136024820152721d995cdd1a5b99c81b9bdd081cdd185c9d1959606a1b604482015260640161036b565b81546001600160781b03808216600160881b90920416106108905760405162461bcd60e51b815260206004820152600b60248201526a18db185a5b595908185b1b60aa1b604482015260640161036b565b5f61089a33610df3565b8354909150819084906011906108c1908490600160881b90046001600160781b0316611640565b82546001600160781b039182166101009390930a92830291909202199091161790555060015460405163a9059cbb60e01b8152336004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303815f875af1158015610932573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109569190611660565b5060408051338152602081018390527f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4910160405180910390a1505050565b61099d611092565b6109a65f6110be565b565b6109b0611092565b8584146109cf5760405162461bcd60e51b815260040161036b906114fa565b8382146109ee5760405162461bcd60e51b815260040161036b906114fa565b5f5b86811015610c4a5760035f898984818110610a0d57610a0d611499565b9050602002016020810190610a229190611479565b6001600160a01b0316815260208101919091526040015f20546001600160781b031615610a875760405162461bcd60e51b815260206004820152601360248201527277686974656c697374656420616c726561647960681b604482015260640161036b565b600254848483818110610a9c57610a9c611499565b9050602002016020810190610ab1919061168c565b61ffff1610610afb5760405162461bcd60e51b81526020600482015260166024820152751a5b9d985b1a59081d995cdd1a5b99d49bdd5b99125960521b604482015260640161036b565b5f868683818110610b0e57610b0e611499565b9050602002016020810190610b2391906116bb565b90508215610b4057610b3d670de0b6b3a7640000826116d4565b90505b6040518060600160405280826001600160781b03168152602001868685818110610b6c57610b6c611499565b9050602002016020810190610b81919061168c565b61ffff1681526020015f6001600160781b031681525060035f8b8b86818110610bac57610bac611499565b9050602002016020810190610bc19190611479565b6001600160a01b0316815260208082019290925260409081015f20835181549385015194909201516001600160781b03908116600160881b0270ffffffffffffffffffffffffffffffffff61ffff909616600160781b0270ffffffffffffffffffffffffffffffffff1990951691909316179290921792909216919091179055506001016109f0565b507f1b07865ca20d6ee20afbce77b41729732bd80ee4661a6321a3e602f4f9746e10878787878787604051610c84969594939291906116ff565b60405180910390a150505050505050565b60408051608080820183525f8083526020808401829052606084860181905280850152858252600481529084902084519283018552805465ffffffffffff8082168552600160301b90910416838301526001810180548651818502810185018852818152959694959294860193830182828015610d5e57602002820191905f5260205f20905f905b82829054906101000a900465ffffffffffff1665ffffffffffff1681526020019060060190602082600501049283019260010382029150808411610d1d5790505b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610de357602002820191905f5260205f20905f905b82829054906101000a900465ffffffffffff1665ffffffffffff1681526020019060060190602082600501049283019260010382029150808411610da25790505b5050505050815250509050919050565b6001600160a01b0381165f9081526003602090815260408083208054600160781b900461ffff16845260049092528220805465ffffffffffff1615610ef4578054600160301b900465ffffffffffff16421115610e79578154610e68906001600160781b03600160881b82048116911661179d565b6001600160781b0316949350505050565b81548154600160881b9091046001600160781b031690610eab9065ffffffffffff80821691600160301b9004166117bd565b825465ffffffffffff91821691610ec3911642611545565b8454610ed891906001600160781b03166117dc565b610ee291906117f3565b610eec9190611545565b949350505050565b5f805b6001830154811015610f9c5742836001018281548110610f1957610f19611499565b905f5260205f2090600591828204019190066006029054906101000a900465ffffffffffff1665ffffffffffff1611610f9c57826002018181548110610f6157610f61611499565b905f5260205f2090600591828204019190066006029054906101000a900465ffffffffffff1682610f929190611577565b9150600101610ef7565b5082546001600160781b03600160881b8204811691620f424091610fca9165ffffffffffff861691166117dc565b610fd491906117f3565b610fde9190611545565b95945050505050565b5f818152600460205260408120805465ffffffffffff1615611012575465ffffffffffff1692915050565b806001015f8154811061102757611027611499565b905f5260205f2090600591828204019190066006029054906101000a900465ffffffffffff16915050919050565b61105d611092565b6001600160a01b03811661108657604051631e4fbdf760e01b81525f600482015260240161036b565b61108f816110be565b50565b5f546001600160a01b031633146109a65760405163118cdaa760e01b815233600482015260240161036b565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b828054828255905f5260205f20906004016005900481019282156111af579160200282015f5b8382111561117b57835183826101000a81548165ffffffffffff021916908365ffffffffffff1602179055509260200192600601602081600501049283019260010302611133565b80156111ad5782816101000a81549065ffffffffffff021916905560060160208160050104928301926001030261117b565b505b506111bb9291506111bf565b5090565b5b808211156111bb575f81556001016111c0565b5f8083601f8401126111e3575f80fd5b50813567ffffffffffffffff8111156111fa575f80fd5b6020830191508360208260051b8501011115611214575f80fd5b9250929050565b5f806020838503121561122c575f80fd5b823567ffffffffffffffff811115611242575f80fd5b61124e858286016111d3565b90969095509350505050565b803565ffffffffffff8116811461126f575f80fd5b919050565b5f805f805f8060808789031215611289575f80fd5b6112928761125a565b95506112a06020880161125a565b9450604087013567ffffffffffffffff808211156112bc575f80fd5b6112c88a838b016111d3565b909650945060608901359150808211156112e0575f80fd5b506112ed89828a016111d3565b979a9699509497509295939492505050565b801515811461108f575f80fd5b5f805f805f805f6080888a031215611322575f80fd5b873567ffffffffffffffff80821115611339575f80fd5b6113458b838c016111d3565b909950975060208a013591508082111561135d575f80fd5b6113698b838c016111d3565b909750955060408a0135915080821115611381575f80fd5b5061138e8a828b016111d3565b90945092505060608801356113a2816112ff565b8091505092959891949750929550565b5f602082840312156113c2575f80fd5b5035919050565b5f815180845260208085019450602084015f5b8381101561140057815165ffffffffffff16875295820195908201906001016113dc565b509495945050505050565b602081525f65ffffffffffff8084511660208401528060208501511660408401525060408301516080606084015261144660a08401826113c9565b90506060840151601f19848303016080850152610fde82826113c9565b80356001600160a01b038116811461126f575f80fd5b5f60208284031215611489575f80fd5b61149282611463565b9392505050565b634e487b7160e01b5f52603260045260245ffd5b8183525f60208085019450825f5b85811015611400576001600160a01b036114d483611463565b16875295820195908201906001016114bb565b602081525f610eec6020830184866114ad565b60208082526017908201527f646966666572656e74206172726179206c656e67746873000000000000000000604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561155857611558611531565b92915050565b5f6020828403121561156e575f80fd5b6114928261125a565b65ffffffffffff81811683821601908082111561159657611596611531565b5092915050565b5f600182016115ae576115ae611531565b5060010190565b8183525f60208085019450825f5b858110156114005765ffffffffffff6115db8361125a565b16875295820195908201906001016115c3565b8781525f65ffffffffffff808916602084015280881660408401525060a0606083015261161f60a0830186886115b5565b82810360808401526116328185876115b5565b9a9950505050505050505050565b6001600160781b0381811683821601908082111561159657611596611531565b5f60208284031215611670575f80fd5b8151611492816112ff565b803561ffff8116811461126f575f80fd5b5f6020828403121561169c575f80fd5b6114928261167b565b80356001600160781b038116811461126f575f80fd5b5f602082840312156116cb575f80fd5b611492826116a5565b6001600160781b038181168382160280821691908281146116f7576116f7611531565b505092915050565b606081525f61171260608301888a6114ad565b828103602084810191909152868252879181015f5b88811015611753576001600160781b03611740856116a5565b1682529282019290820190600101611727565b50848103604086015285815281019150855f5b8681101561178d5761ffff61177a8361167b565b1684529282019290820190600101611766565b50919a9950505050505050505050565b6001600160781b0382811682821603908082111561159657611596611531565b65ffffffffffff82811682821603908082111561159657611596611531565b808202811582820484141761155857611558611531565b5f8261180d57634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220b14e88903238b3294428ae1712ac3ecf471e5dd5a8f4a6d0833df928f5fb1c6d64736f6c63430008160033

Verified Source Code Partial Match

Compiler: v0.8.22+commit.4fc1097e EVM: shanghai Optimization: Yes (200 runs)
VRVesting.sol 397 lines
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

// File: @openzeppelin/contracts/interfaces/IERC20.sol


// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;


// File: @openzeppelin/contracts/utils/Context.sol


// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;


/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// File: vesting.sol


pragma solidity ^0.8.0;



contract VRVesting is Ownable {
    uint48 public constant HUNDRED_PERCENT = 1e6;

    struct User {
        uint120 amount;
        uint16 vestingRoundId;
        uint120 claimed;
    }

    struct VestingRound { 
        uint48 linearVestingStart;
        uint48 linearVestingEnd;
        uint48[] unlockTimestamps;
        uint48[] unlockPercentages;
    }

    IERC20 public token;
    uint public vestingRoundCount;
    mapping(address => User) public users;
    mapping(uint => VestingRound) vestingRounds;

    event Claim(address user, uint amount);
    event AddVestingRound(uint id, uint48 linearVestingStart, uint48 linearVestingEnd, uint48[] unlockTimestamps, uint48[] unlockPercentages);
    event AddWallets(address[] wallets, uint120[] amounts, uint16[] vestingRoundIds);
    event DeleteWallets(address[] wallets);

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

    // ======================= OWNER FUNCTIONS ======================= //

    function addVestingRound(
        uint48 linearVestingStart,
        uint48 linearVestingEnd,
        uint48[] calldata unlockTimestamps,
        uint48[] calldata unlockPercentages
    ) external onlyOwner {
        if (linearVestingStart > 0) {
            require(unlockTimestamps.length == 0, "unlockTimestamps not empty");
            require(unlockPercentages.length == 0, "unlockPercentages not empty");
            require(linearVestingEnd > linearVestingStart, "end > start timestamp");
        } else {
            require(linearVestingEnd == 0, "linearVestingEnd not zero");
            require(unlockTimestamps.length == unlockPercentages.length, "different array lengths");
            
            for (uint i = 1; i < unlockTimestamps.length; i++) {
                require(unlockTimestamps[i] > unlockTimestamps[i - 1], "invalid unlockTimestamps");
            }

            uint48 unlockPercentagesSum = 0;
            for (uint i = 0; i < unlockPercentages.length; i++) {
                unlockPercentagesSum += unlockPercentages[i];
            } 
            require(unlockPercentagesSum == HUNDRED_PERCENT, "unlockPercentages sum not 100%");
        }

        vestingRounds[vestingRoundCount++] = VestingRound(
            linearVestingStart,
            linearVestingEnd,
            unlockTimestamps,
            unlockPercentages
        );

        emit AddVestingRound(vestingRoundCount - 1, linearVestingStart, linearVestingEnd, unlockTimestamps, unlockPercentages);
    }

    function addWallets(
        address[] calldata wallets,
        uint120[] calldata amounts,
        uint16[] calldata vestingRoundIds,
        bool applyDecimals
    ) external onlyOwner {
        require(wallets.length == amounts.length, "different array lengths");
        require(amounts.length == vestingRoundIds.length, "different array lengths");

        for (uint i; i < wallets.length; i++) {
            require(users[wallets[i]].amount == 0, "whitelisted already");
            require(vestingRoundIds[i] < vestingRoundCount, "invalid vestingRoundId");

            uint120 amount = amounts[i];
            if (applyDecimals) {
                amount *= 1e18;
            }

            users[wallets[i]] = User(
                amount,
                vestingRoundIds[i],
                0
            );
        }

        emit AddWallets(wallets, amounts, vestingRoundIds);
    }

    function deleteWallets(
        address[] calldata wallets
    ) external onlyOwner {
        for (uint i; i < wallets.length; i++) {
            delete users[wallets[i]];
        }

        emit DeleteWallets(wallets);
    }

    // ======================= EXTERNAL FUNCTIONS ======================= //

    function claim() external {
        User storage user = users[msg.sender];

        uint48 vestingStart = getVestingStart(user.vestingRoundId);

        require(user.amount > 0, "not whitelisted");
        require(block.timestamp > vestingStart, "vesting not started");
        require(user.claimed < user.amount, "claimed all");

        uint claimable = getClaimable(msg.sender);

        user.claimed += uint120(claimable);
        token.transfer(msg.sender, claimable);

        emit Claim(msg.sender, claimable);
    }

    // ======================= VIEW FUNCTIONS ======================= //

    function getVestingStart(uint vestingRoundId) public view returns (uint48) {
        VestingRound storage vestingRound = vestingRounds[vestingRoundId];

        if (vestingRound.linearVestingStart > 0) {
            return vestingRound.linearVestingStart;
        } else {
            return vestingRound.unlockTimestamps[0];
        }
    }

    function getClaimable(
        address wallet
    ) public view returns (uint) {
        User storage user = users[wallet];
        VestingRound storage vestingRound = vestingRounds[user.vestingRoundId];

        if (vestingRound.linearVestingStart > 0) {
            if (block.timestamp > vestingRound.linearVestingEnd) {
                return user.amount - user.claimed;
            } else {
                return uint(user.amount) * (block.timestamp - vestingRound.linearVestingStart) / (vestingRound.linearVestingEnd - vestingRound.linearVestingStart) - user.claimed;
            }
        } else {
            uint48 cumulativePercentage = 0;
            for (uint i; i < vestingRound.unlockTimestamps.length; i++) {
                if (vestingRound.unlockTimestamps[i] > block.timestamp) {
                    break;
                }
                cumulativePercentage += vestingRound.unlockPercentages[i];
            }

            return uint(user.amount) * cumulativePercentage / HUNDRED_PERCENT - user.claimed;
        }
    }

    function getVestingRound(
        uint vestingRoundId
    ) external view returns (VestingRound memory vestingRound) {
        return vestingRounds[vestingRoundId];
    }
}

Read Contract

HUNDRED_PERCENT 0x6ed93dd0 → uint48
getClaimable 0xa583024b → uint256
getVestingRound 0x95aa6d2d → tuple
getVestingStart 0xca2324eb → uint48
owner 0x8da5cb5b → address
token 0xfc0c546a → address
users 0xa87430ba → uint120, uint16, uint120
vestingRoundCount 0x7130b0eb → uint256

Write Contract 6 functions

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

addVestingRound 0x45a5405b
uint48 linearVestingStart
uint48 linearVestingEnd
uint48[] unlockTimestamps
uint48[] unlockPercentages
addWallets 0x8eab5d00
address[] wallets
uint120[] amounts
uint16[] vestingRoundIds
bool applyDecimals
claim 0x4e71d92d
No parameters
deleteWallets 0x21888989
address[] wallets
renounceOwnership 0x715018a6
No parameters
transferOwnership 0xf2fde38b
address newOwner

Recent Transactions

No transactions found for this address