ETH Price: $3,458.67 (-0.71%)
Gas: 3 Gwei

Contract

0xC0fde70A65C7569Fe919bE57492228DEE8cDb585
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value

There are no matching entries

Please try again later

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To Value
177782992023-07-26 15:58:47341 days ago1690387127  Contract Creation0 ETH
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x29067F28...f58ABdBBe
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
Airdrop

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, GNU LGPLv3 license
File 1 of 5 : Airdrop.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0 <0.9.0;

import "./vendor/@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./vendor/@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "./interfaces/ModuleManager.sol";
import "./VestingPool.sol";

/// @title Airdrop contract
/// @author Richard Meissner - @rmeissner
contract Airdrop is VestingPool {
    // Root of the Merkle tree
    bytes32 public root;
    // Time until which the airdrop can be redeemed
    uint64 public immutable redeemDeadline;

    /// @notice Creates the airdrop for the token at address `_token` and `_manager` as the manager. The airdrop can be redeemed until `_redeemDeadline`.
    /// @param _token The token that should be used for the airdrop
    /// @param _manager The manager of this airdrop (e.g. the address that can call `initializeRoot`)
    /// @param _redeemDeadline The deadline until when the airdrop could be redeemed (if inititalized). This needs to be a date in the future.
    constructor(
        address _token,
        address _manager,
        uint64 _redeemDeadline
    ) VestingPool(_token, _manager) {
        require(_redeemDeadline > block.timestamp, "Redeem deadline should be in the future");
        redeemDeadline = _redeemDeadline;
    }

    /// @notice Initialize the airdrop with `_root` as the Merkle root.
    /// @dev This can only be called once
    /// @param _root The Merkle root that should be set for this contract
    function initializeRoot(bytes32 _root) public onlyPoolManager {
        require(root == bytes32(0), "State root already initialized");
        root = _root;
    }

    /// @notice Creates a vesting authorized by the Merkle proof.
    /// @dev It is required that the pool has enough tokens available
    /// @dev Vesting will be created for msg.sender
    /// @param curveType Type of the curve that should be used for the vesting
    /// @param durationWeeks The duration of the vesting in weeks
    /// @param startDate The date when the vesting should be started (can be in the past)
    /// @param amount Amount of tokens that should be vested in atoms
    /// @param proof Proof to redeem tokens
    function redeem(
        uint8 curveType,
        uint16 durationWeeks,
        uint64 startDate,
        uint128 amount,
        bytes32[] calldata proof
    ) external {
        require(block.timestamp <= redeemDeadline, "Deadline to redeem vesting has been exceeded");
        require(root != bytes32(0), "State root not initialized");
        // This call will fail if the vesting was already created
        bytes32 vestingId = _addVesting(msg.sender, curveType, false, durationWeeks, startDate, amount);
        require(MerkleProof.verify(proof, root, vestingId), "Invalid merkle proof");
    }

    /// @notice Claim `tokensToClaim` tokens from vesting `vestingId` and transfer them to the `beneficiary`.
    /// @dev This can only be called by the owner of the vesting
    /// @dev Beneficiary cannot be the 0-address
    /// @dev This will trigger a transfer of tokens via a module transaction
    /// @param vestingId Id of the vesting from which the tokens should be claimed
    /// @param beneficiary Account that should receive the claimed tokens
    /// @param tokensToClaim Amount of tokens to claim in atoms or max uint128 to claim all available
    function claimVestedTokensViaModule(
        bytes32 vestingId,
        address beneficiary,
        uint128 tokensToClaim
    ) public {
        uint128 tokensClaimed = updateClaimedTokens(vestingId, beneficiary, tokensToClaim);
        // Approve pool manager to transfer tokens on behalf of the pool
        require(IERC20(token).approve(poolManager, tokensClaimed), "Could not approve tokens");
        // Check state prior to transfer
        uint256 balancePoolBefore = IERC20(token).balanceOf(address(this));
        uint256 balanceBeneficiaryBefore = IERC20(token).balanceOf(beneficiary);
        // Build transfer data to call token contract via the pool manager
        bytes memory transferData = abi.encodeWithSignature(
            "transferFrom(address,address,uint256)",
            address(this),
            beneficiary,
            tokensClaimed
        );
        // Trigger transfer of tokens from this pool to the beneficiary via the pool manager as a module transaction
        require(ModuleManager(poolManager).execTransactionFromModule(token, 0, transferData, 0), "Module transaction failed");
        // Set allowance to 0 to avoid any left over allowance. (Note: this should be impossible for normal ERC20 tokens)
        require(IERC20(token).approve(poolManager, 0), "Could not set token allowance to 0");
        // Check state after the transfer
        uint256 balancePoolAfter = IERC20(token).balanceOf(address(this));
        uint256 balanceBeneficiaryAfter = IERC20(token).balanceOf(beneficiary);
        require(balancePoolAfter == balancePoolBefore - tokensClaimed, "Could not deduct tokens from pool");
        require(balanceBeneficiaryAfter == balanceBeneficiaryBefore + tokensClaimed, "Could not add tokens to beneficiary");
    }

    /// @notice Claims all tokens that have not been redeemed before `redeemDeadline`
    /// @dev Can only be called after `redeemDeadline` has been reached.
    /// @param beneficiary Account that should receive the claimed tokens
    function claimUnusedTokens(address beneficiary) external onlyPoolManager {
        require(block.timestamp > redeemDeadline, "Tokens can still be redeemed");
        uint256 unusedTokens = tokensAvailableForVesting();
        require(unusedTokens > 0, "No tokens to claim");
        require(IERC20(token).transfer(beneficiary, unusedTokens), "Token transfer failed");
    }

    /// @dev This method cannot be called on this contract
    function addVesting(
        address,
        uint8,
        bool,
        uint16,
        uint64,
        uint128
    ) public pure override {
        revert("This method is not available for this contract");
    }
}

File 2 of 5 : VestingPool.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0 <0.9.0;
import "./vendor/@openzeppelin/contracts/token/ERC20/IERC20.sol";

/// @title Vesting contract for multiple accounts
/// @author Richard Meissner - @rmeissner
contract VestingPool {
    event AddedVesting(bytes32 indexed id, address indexed account);
    event ClaimedVesting(bytes32 indexed id, address indexed account, address indexed beneficiary);
    event PausedVesting(bytes32 indexed id);
    event UnpausedVesting(bytes32 indexed id);
    event CancelledVesting(bytes32 indexed id);

    // Sane limits based on: https://eips.ethereum.org/EIPS/eip-1985
    // amountClaimed should always be equal to or less than amount
    // pausingDate should always be equal to or greater than startDate
    struct Vesting {
        // First storage slot
        address account; // 20 bytes
        uint8 curveType; // 1 byte -> Max 256 different curve types
        bool managed; // 1 byte
        uint16 durationWeeks; // 2 bytes -> Max 65536 weeks ~ 1260 years
        uint64 startDate; // 8 bytes -> Works until year 292278994, but not before 1970
        // Second storage slot
        uint128 amount; // 16 bytes -> Max 3.4e20 tokens (including decimals)
        uint128 amountClaimed; // 16 bytes -> Max 3.4e20 tokens (including decimals)
        // Third storage slot
        uint64 pausingDate; // 8 bytes -> Works until year 292278994, but not before 1970
        bool cancelled; // 1 byte
    }

    // keccak256(
    //     "EIP712Domain(uint256 chainId,address verifyingContract)"
    // );
    bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218;

    // keccak256(
    //     "Vesting(address account,uint8 curveType,bool managed,uint16 durationWeeks,uint64 startDate,uint128 amount)"
    // );
    bytes32 private constant VESTING_TYPEHASH = 0x43838b5ce9ca440d1ac21b07179a1fdd88aa2175e5ea103f6e37aa6d18ce78ad;

    address public immutable token;
    address public immutable poolManager;

    uint256 public totalTokensInVesting;
    mapping(bytes32 => Vesting) public vestings;

    modifier onlyPoolManager() {
        require(msg.sender == poolManager, "Can only be called by pool manager");
        _;
    }

    constructor(address _token, address _poolManager) {
        token = _token;
        poolManager = _poolManager;
    }

    /// @notice Create a vesting on this pool for `account`.
    /// @dev This can only be called by the pool manager
    /// @dev It is required that the pool has enough tokens available
    /// @param account The account for which the vesting is created
    /// @param curveType Type of the curve that should be used for the vesting
    /// @param managed Boolean that indicates if the vesting can be managed by the pool manager
    /// @param durationWeeks The duration of the vesting in weeks
    /// @param startDate The date when the vesting should be started (can be in the past)
    /// @param amount Amount of tokens that should be vested in atoms
    function addVesting(
        address account,
        uint8 curveType,
        bool managed,
        uint16 durationWeeks,
        uint64 startDate,
        uint128 amount
    ) public virtual onlyPoolManager {
        _addVesting(account, curveType, managed, durationWeeks, startDate, amount);
    }

    /// @notice Calculate the amount of tokens available for new vestings.
    /// @dev This value changes when more tokens are deposited to this contract
    /// @return Amount of tokens that can be used for new vestings.
    function tokensAvailableForVesting() public view virtual returns (uint256) {
        return IERC20(token).balanceOf(address(this)) - totalTokensInVesting;
    }

    /// @notice Create a vesting on this pool for `account`.
    /// @dev It is required that the pool has enough tokens available
    /// @dev Account cannot be zero address
    /// @param account The account for which the vesting is created
    /// @param curveType Type of the curve that should be used for the vesting
    /// @param managed Boolean that indicates if the vesting can be managed by the pool manager
    /// @param durationWeeks The duration of the vesting in weeks
    /// @param startDate The date when the vesting should be started (can be in the past)
    /// @param amount Amount of tokens that should be vested in atoms
    /// @param vestingId The id of the created vesting
    function _addVesting(
        address account,
        uint8 curveType,
        bool managed,
        uint16 durationWeeks,
        uint64 startDate,
        uint128 amount
    ) internal returns (bytes32 vestingId) {
        require(account != address(0), "Invalid account");
        require(curveType < 2, "Invalid vesting curve");
        vestingId = vestingHash(account, curveType, managed, durationWeeks, startDate, amount);
        require(vestings[vestingId].account == address(0), "Vesting id already used");
        // Check that enough tokens are available for the new vesting
        uint256 availableTokens = tokensAvailableForVesting();
        require(availableTokens >= amount, "Not enough tokens available");
        // Mark tokens for this vesting in use
        totalTokensInVesting += amount;
        vestings[vestingId] = Vesting({
            account: account,
            curveType: curveType,
            managed: managed,
            durationWeeks: durationWeeks,
            startDate: startDate,
            amount: amount,
            amountClaimed: 0,
            pausingDate: 0,
            cancelled: false
        });
        emit AddedVesting(vestingId, account);
    }

    /// @notice Claim `tokensToClaim` tokens from vesting `vestingId` and transfer them to the `beneficiary`.
    /// @dev This can only be called by the owner of the vesting
    /// @dev Beneficiary cannot be the 0-address
    /// @dev This will trigger a transfer of tokens
    /// @param vestingId Id of the vesting from which the tokens should be claimed
    /// @param beneficiary Account that should receive the claimed tokens
    /// @param tokensToClaim Amount of tokens to claim in atoms or max uint128 to claim all available
    function claimVestedTokens(
        bytes32 vestingId,
        address beneficiary,
        uint128 tokensToClaim
    ) public {
        uint128 tokensClaimed = updateClaimedTokens(vestingId, beneficiary, tokensToClaim);
        require(IERC20(token).transfer(beneficiary, tokensClaimed), "Token transfer failed");
    }

    /// @notice Update `amountClaimed` on vesting `vestingId` by `tokensToClaim` tokens.
    /// @dev This can only be called by the owner of the vesting
    /// @dev Beneficiary cannot be the 0-address
    /// @dev This will only update the internal state and NOT trigger the transfer of tokens.
    /// @param vestingId Id of the vesting from which the tokens should be claimed
    /// @param beneficiary Account that should receive the claimed tokens
    /// @param tokensToClaim Amount of tokens to claim in atoms or max uint128 to claim all available
    /// @param tokensClaimed Amount of tokens that have been newly claimed by calling this method
    function updateClaimedTokens(
        bytes32 vestingId,
        address beneficiary,
        uint128 tokensToClaim
    ) internal returns (uint128 tokensClaimed) {
        require(beneficiary != address(0), "Cannot claim to 0-address");
        Vesting storage vesting = vestings[vestingId];
        require(vesting.account == msg.sender, "Can only be claimed by vesting owner");
        // Calculate how many tokens can be claimed
        uint128 availableClaim = _calculateVestedAmount(vesting) - vesting.amountClaimed;
        // If max uint128 is used, claim all available tokens.
        tokensClaimed = tokensToClaim == type(uint128).max ? availableClaim : tokensToClaim;
        require(tokensClaimed <= availableClaim, "Trying to claim too many tokens");
        // Adjust how many tokens are locked in vesting
        totalTokensInVesting -= tokensClaimed;
        vesting.amountClaimed += tokensClaimed;
        emit ClaimedVesting(vestingId, vesting.account, beneficiary);
    }

    /// @notice Cancel vesting `vestingId`.
    /// @dev This can only be called by the pool manager
    /// @dev Only manageable vestings can be cancelled
    /// @param vestingId Id of the vesting that should be cancelled
    function cancelVesting(bytes32 vestingId) public onlyPoolManager {
        Vesting storage vesting = vestings[vestingId];
        require(vesting.account != address(0), "Vesting not found");
        require(vesting.managed, "Only managed vestings can be cancelled");
        require(!vesting.cancelled, "Vesting already cancelled");
        bool isFutureVesting = block.timestamp <= vesting.startDate;
        // If vesting is not already paused it will be paused
        // Pausing date should not be reset else tokens of the initial pause can be claimed
        if (vesting.pausingDate == 0) {
            // pausingDate should always be larger or equal to startDate
            vesting.pausingDate = isFutureVesting ? vesting.startDate : uint64(block.timestamp);
        }
        // Vesting is cancelled, therefore tokens that are not vested yet, will be added back to the pool
        uint128 unusedToken = isFutureVesting ? vesting.amount : vesting.amount - _calculateVestedAmount(vesting);
        totalTokensInVesting -= unusedToken;
        // Vesting is set to cancelled and therefore disallows unpausing
        vesting.cancelled = true;
        emit CancelledVesting(vestingId);
    }

    /// @notice Pause vesting `vestingId`.
    /// @dev This can only be called by the pool manager
    /// @dev Only manageable vestings can be paused
    /// @param vestingId Id of the vesting that should be paused
    function pauseVesting(bytes32 vestingId) public onlyPoolManager {
        Vesting storage vesting = vestings[vestingId];
        require(vesting.account != address(0), "Vesting not found");
        require(vesting.managed, "Only managed vestings can be paused");
        require(vesting.pausingDate == 0, "Vesting already paused");
        // pausingDate should always be larger or equal to startDate
        vesting.pausingDate = block.timestamp <= vesting.startDate ? vesting.startDate : uint64(block.timestamp);
        emit PausedVesting(vestingId);
    }

    /// @notice Unpause vesting `vestingId`.
    /// @dev This can only be called by the pool manager
    /// @dev Only vestings that have not been cancelled can be unpaused
    /// @param vestingId Id of the vesting that should be unpaused
    function unpauseVesting(bytes32 vestingId) public onlyPoolManager {
        Vesting storage vesting = vestings[vestingId];
        require(vesting.account != address(0), "Vesting not found");
        require(vesting.pausingDate != 0, "Vesting is not paused");
        require(!vesting.cancelled, "Vesting has been cancelled and cannot be unpaused");
        // Calculate the time the vesting was paused
        // If vesting has not started yet, then pausing date might be in the future
        uint64 timePaused = block.timestamp <= vesting.pausingDate ? 0 : uint64(block.timestamp) - vesting.pausingDate;
        // Offset the start date to create the effect of pausing
        vesting.startDate = vesting.startDate + timePaused;
        vesting.pausingDate = 0;
        emit UnpausedVesting(vestingId);
    }

    /// @notice Calculate vested and claimed token amounts for vesting `vestingId`.
    /// @dev This will revert if the vesting has not been started yet
    /// @param vestingId Id of the vesting for which to calculate the amounts
    /// @return vestedAmount The amount in atoms of tokens vested
    /// @return claimedAmount The amount in atoms of tokens claimed
    function calculateVestedAmount(bytes32 vestingId) external view returns (uint128 vestedAmount, uint128 claimedAmount) {
        Vesting storage vesting = vestings[vestingId];
        require(vesting.account != address(0), "Vesting not found");
        vestedAmount = _calculateVestedAmount(vesting);
        claimedAmount = vesting.amountClaimed;
    }

    /// @notice Calculate vested token amount for vesting `vesting`.
    /// @dev This will revert if the vesting has not been started yet
    /// @param vesting The vesting for which to calculate the amounts
    /// @return vestedAmount The amount in atoms of tokens vested
    function _calculateVestedAmount(Vesting storage vesting) internal view returns (uint128 vestedAmount) {
        require(vesting.startDate <= block.timestamp, "Vesting not active yet");
        // Convert vesting duration to seconds
        uint64 durationSeconds = uint64(vesting.durationWeeks) * 7 * 24 * 60 * 60;
        // If contract is paused use the pausing date to calculate amount
        uint64 vestedSeconds = vesting.pausingDate > 0
            ? vesting.pausingDate - vesting.startDate
            : uint64(block.timestamp) - vesting.startDate;
        if (vestedSeconds >= durationSeconds) {
            // If vesting time is longer than duration everything has been vested
            vestedAmount = vesting.amount;
        } else if (vesting.curveType == 0) {
            // Linear vesting
            vestedAmount = calculateLinear(vesting.amount, vestedSeconds, durationSeconds);
        } else if (vesting.curveType == 1) {
            // Exponential vesting
            vestedAmount = calculateExponential(vesting.amount, vestedSeconds, durationSeconds);
        } else {
            // This is unreachable because it is not possible to add a vesting with an invalid curve type
            revert("Invalid curve type");
        }
    }

    /// @notice Calculate vested token amount on a linear curve.
    /// @dev Calculate vested amount on linear curve: targetAmount * elapsedTime / totalTime
    /// @param targetAmount Amount of tokens that is being vested
    /// @param elapsedTime Time that has elapsed for the vesting
    /// @param totalTime Duration of the vesting
    /// @return Tokens that have been vested on a linear curve
    function calculateLinear(
        uint128 targetAmount,
        uint64 elapsedTime,
        uint64 totalTime
    ) internal pure returns (uint128) {
        // Calculate vested amount on linear curve: targetAmount * elapsedTime / totalTime
        uint256 amount = (uint256(targetAmount) * uint256(elapsedTime)) / uint256(totalTime);
        require(amount <= type(uint128).max, "Overflow in curve calculation");
        return uint128(amount);
    }

    /// @notice Calculate vested token amount on an exponential curve.
    /// @dev Calculate vested amount on exponential curve: targetAmount * elapsedTime^2 / totalTime^2
    /// @param targetAmount Amount of tokens that is being vested
    /// @param elapsedTime Time that has elapsed for the vesting
    /// @param totalTime Duration of the vesting
    /// @return Tokens that have been vested on an exponential curve
    function calculateExponential(
        uint128 targetAmount,
        uint64 elapsedTime,
        uint64 totalTime
    ) internal pure returns (uint128) {
        // Calculate vested amount on exponential curve: targetAmount * elapsedTime^2 / totalTime^2
        uint256 amount = (uint256(targetAmount) * uint256(elapsedTime) * uint256(elapsedTime)) / (uint256(totalTime) * uint256(totalTime));
        require(amount <= type(uint128).max, "Overflow in curve calculation");
        return uint128(amount);
    }

    /// @notice Calculate the id for a vesting based on its parameters.
    /// @dev The id is a EIP-712 based hash of the vesting.
    /// @param account The account for which the vesting was created
    /// @param curveType Type of the curve that is used for the vesting
    /// @param managed Indicator if the vesting is managed by the pool manager
    /// @param durationWeeks The duration of the vesting in weeks
    /// @param startDate The date when the vesting started (can be in the future)
    /// @param amount Amount of tokens that are vested in atoms
    /// @return vestingId Id of a vesting based on its parameters
    function vestingHash(
        address account,
        uint8 curveType,
        bool managed,
        uint16 durationWeeks,
        uint64 startDate,
        uint128 amount
    ) public view returns (bytes32 vestingId) {
        bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this));
        bytes32 vestingDataHash = keccak256(abi.encode(VESTING_TYPEHASH, account, curveType, managed, durationWeeks, startDate, amount));
        vestingId = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0x01), domainSeparator, vestingDataHash));
    }
}

File 3 of 5 : ModuleManager.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0 <0.9.0;

interface ModuleManager {
    /// @notice Allows a module to execute a Safe transaction.
    /// @dev The implementation of the interface might require that the module is enabled (e.g. for the Safe contracts via enableModule) and could revert otherwise
    /// @param to Destination address of module transaction.
    /// @param value Ether value of module transaction.
    /// @param data Data payload of module transaction.
    /// @param operation Operation type of module transaction.
    /// @param success Indicates if the Safe transaction was executed successfully or not
    function execTransactionFromModule(
        address to,
        uint256 value,
        bytes memory data,
        uint8 operation
    ) external returns (bool success);
}

File 4 of 5 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` 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 amount
    ) external returns (bool);

    /**
     * @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);
}

File 5 of 5 : MerkleProof.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Trees proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];
            if (computedHash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = _efficientHash(computedHash, proofElement);
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = _efficientHash(proofElement, computedHash);
            }
        }
        return computedHash;
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

Settings
{
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_manager","type":"address"},{"internalType":"uint64","name":"_redeemDeadline","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AddedVesting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"CancelledVesting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"}],"name":"ClaimedVesting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"PausedVesting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"UnpausedVesting","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"uint128","name":"","type":"uint128"}],"name":"addVesting","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vestingId","type":"bytes32"}],"name":"calculateVestedAmount","outputs":[{"internalType":"uint128","name":"vestedAmount","type":"uint128"},{"internalType":"uint128","name":"claimedAmount","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vestingId","type":"bytes32"}],"name":"cancelVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"}],"name":"claimUnusedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vestingId","type":"bytes32"},{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint128","name":"tokensToClaim","type":"uint128"}],"name":"claimVestedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vestingId","type":"bytes32"},{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint128","name":"tokensToClaim","type":"uint128"}],"name":"claimVestedTokensViaModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_root","type":"bytes32"}],"name":"initializeRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vestingId","type":"bytes32"}],"name":"pauseVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"poolManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"curveType","type":"uint8"},{"internalType":"uint16","name":"durationWeeks","type":"uint16"},{"internalType":"uint64","name":"startDate","type":"uint64"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redeemDeadline","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"root","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensAvailableForVesting","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokensInVesting","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vestingId","type":"bytes32"}],"name":"unpauseVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint8","name":"curveType","type":"uint8"},{"internalType":"bool","name":"managed","type":"bool"},{"internalType":"uint16","name":"durationWeeks","type":"uint16"},{"internalType":"uint64","name":"startDate","type":"uint64"},{"internalType":"uint128","name":"amount","type":"uint128"}],"name":"vestingHash","outputs":[{"internalType":"bytes32","name":"vestingId","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"vestings","outputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint8","name":"curveType","type":"uint8"},{"internalType":"bool","name":"managed","type":"bool"},{"internalType":"uint16","name":"durationWeeks","type":"uint16"},{"internalType":"uint64","name":"startDate","type":"uint64"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint128","name":"amountClaimed","type":"uint128"},{"internalType":"uint64","name":"pausingDate","type":"uint64"},{"internalType":"bool","name":"cancelled","type":"bool"}],"stateMutability":"view","type":"function"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101155760003560e01c80638899f311116100a2578063bf6213e411610071578063bf6213e4146102bc578063d7faa145146102d8578063dc4c90d314610309578063ebf0c71714610327578063fc0c546a1461034557610115565b80638899f3111461022e5780638f5b3c3b1461024c5780639fb0c41d14610268578063a27c7a02146102a057610115565b80632bafa73c116100e95780632bafa73c1461018c5780632e0427aa146101a85780633034d534146101c65780635d76df6b146101e25780636cbab0791461021257610115565b806287b83f1461011a578063073804811461013657806307861fe614610154578063166bbd3b14610170575b600080fd5b610134600480360381019061012f91906129c4565b610363565b005b61013e610a47565b60405161014b9190612a30565b60405180910390f35b61016e60048036038101906101699190612a4b565b610a4d565b005b61018a600480360381019061018591906129c4565b610b2c565b005b6101a660048036038101906101a19190612a4b565b610c1e565b005b6101b0610eb2565b6040516101bd9190612a30565b60405180910390f35b6101e060048036038101906101db9190612a4b565b610f5f565b005b6101fc60048036038101906101f79190612b63565b611256565b6040516102099190612bff565b60405180910390f35b61022c60048036038101906102279190612b63565b611346565b005b610236611381565b6040516102439190612c29565b60405180910390f35b61026660048036038101906102619190612a4b565b6113a5565b005b610282600480360381019061027d9190612a4b565b611704565b60405161029799989796959493929190612c8f565b60405180910390f35b6102ba60048036038101906102b59190612d1c565b611807565b005b6102d660048036038101906102d19190612dae565b611a31565b005b6102f260048036038101906102ed9190612a4b565b611b8f565b604051610300929190612e48565b60405180910390f35b610311611c71565b60405161031e9190612e71565b60405180910390f35b61032f611c95565b60405161033c9190612bff565b60405180910390f35b61034d611c9b565b60405161035a9190612e71565b60405180910390f35b6000610370848484611cbf565b90507f0000000000000000000000005afe3855358e112b5647b952709e6165e1c1eeee73ffffffffffffffffffffffffffffffffffffffff1663095ea7b37f0000000000000000000000008cf60b289f8d31f737049b590b5e4285ff0bd1d1836040518363ffffffff1660e01b81526004016103ed929190612ec7565b6020604051808303816000875af115801561040c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104309190612f05565b61046f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046690612f8f565b60405180910390fd5b60007f0000000000000000000000005afe3855358e112b5647b952709e6165e1c1eeee73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016104ca9190612e71565b602060405180830381865afa1580156104e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050b9190612fdb565b905060007f0000000000000000000000005afe3855358e112b5647b952709e6165e1c1eeee73ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b81526004016105689190612e71565b602060405180830381865afa158015610585573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a99190612fdb565b905060003086856040516024016105c293929190613008565b6040516020818303038152906040527f23b872dd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090507f0000000000000000000000008cf60b289f8d31f737049b590b5e4285ff0bd1d173ffffffffffffffffffffffffffffffffffffffff1663468721a77f0000000000000000000000005afe3855358e112b5647b952709e6165e1c1eeee60008460006040518563ffffffff1660e01b81526004016106c29493929190613144565b6020604051808303816000875af11580156106e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107059190612f05565b610744576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161073b906131dc565b60405180910390fd5b7f0000000000000000000000005afe3855358e112b5647b952709e6165e1c1eeee73ffffffffffffffffffffffffffffffffffffffff1663095ea7b37f0000000000000000000000008cf60b289f8d31f737049b590b5e4285ff0bd1d160006040518363ffffffff1660e01b81526004016107c09291906131fc565b6020604051808303816000875af11580156107df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108039190612f05565b610842576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083990613297565b60405180910390fd5b60007f0000000000000000000000005afe3855358e112b5647b952709e6165e1c1eeee73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161089d9190612e71565b602060405180830381865afa1580156108ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108de9190612fdb565b905060007f0000000000000000000000005afe3855358e112b5647b952709e6165e1c1eeee73ffffffffffffffffffffffffffffffffffffffff166370a08231896040518263ffffffff1660e01b815260040161093b9190612e71565b602060405180830381865afa158015610958573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097c9190612fdb565b9050856fffffffffffffffffffffffffffffffff168561099c91906132e6565b82146109dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109d49061338c565b60405180910390fd5b856fffffffffffffffffffffffffffffffff16846109fb91906133ac565b8114610a3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a3390613474565b60405180910390fd5b505050505050505050565b60005481565b7f0000000000000000000000008cf60b289f8d31f737049b590b5e4285ff0bd1d173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610adb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad290613506565b60405180910390fd5b6000801b60025414610b22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1990613572565b60405180910390fd5b8060028190555050565b6000610b39848484611cbf565b90507f0000000000000000000000005afe3855358e112b5647b952709e6165e1c1eeee73ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84836040518363ffffffff1660e01b8152600401610b96929190612ec7565b6020604051808303816000875af1158015610bb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd99190612f05565b610c18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c0f906135de565b60405180910390fd5b50505050565b7f0000000000000000000000008cf60b289f8d31f737049b590b5e4285ff0bd1d173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610cac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ca390613506565b60405180910390fd5b6000600160008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610d57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d4e9061364a565b60405180910390fd5b8060000160159054906101000a900460ff16610da8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d9f906136dc565b60405180910390fd5b60008160020160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1614610e0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0490613748565b60405180910390fd5b8060000160189054906101000a900467ffffffffffffffff1667ffffffffffffffff16421115610e3d5742610e57565b8060000160189054906101000a900467ffffffffffffffff165b8160020160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550817f871860f90ed272e98149ef133136694f00424a57465aa85bfc2535dfd4d450b860405160405180910390a25050565b600080547f0000000000000000000000005afe3855358e112b5647b952709e6165e1c1eeee73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610f0f9190612e71565b602060405180830381865afa158015610f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f509190612fdb565b610f5a91906132e6565b905090565b7f0000000000000000000000008cf60b289f8d31f737049b590b5e4285ff0bd1d173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610fed576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fe490613506565b60405180910390fd5b6000600160008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611098576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161108f9061364a565b60405180910390fd5b60008160020160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1614156110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f5906137b4565b60405180910390fd5b8060020160089054906101000a900460ff1615611150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114790613846565b60405180910390fd5b60008160020160009054906101000a900467ffffffffffffffff1667ffffffffffffffff164211156111a5578160020160009054906101000a900467ffffffffffffffff16426111a09190613866565b6111a8565b60005b9050808260000160189054906101000a900467ffffffffffffffff166111ce919061389a565b8260000160186101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060008260020160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550827f1bf30dbd59905813e462b38cc5a44f3aadd0ee101ec6d7537139f5c7f8a9868560405160405180910390a2505050565b6000807f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a7946921860001b46306040516020016112919392919061392d565b60405160208183030381529060405280519060200120905060007f43838b5ce9ca440d1ac21b07179a1fdd88aa2175e5ea103f6e37aa6d18ce78ad60001b8989898989896040516020016112eb9796959493929190613964565b604051602081830303815290604052805190602001209050601960f81b600160f81b83836040516020016113229493929190613a41565b60405160208183030381529060405280519060200120925050509695505050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137890613b01565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000653b8a2081565b7f0000000000000000000000008cf60b289f8d31f737049b590b5e4285ff0bd1d173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611433576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161142a90613506565b60405180910390fd5b6000600160008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156114de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d59061364a565b60405180910390fd5b8060000160159054906101000a900460ff1661152f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161152690613b93565b60405180910390fd5b8060020160089054906101000a900460ff1615611581576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161157890613bff565b60405180910390fd5b60008160000160189054906101000a900467ffffffffffffffff1667ffffffffffffffff16421115905060008260020160009054906101000a900467ffffffffffffffff1667ffffffffffffffff16141561162657806115e157426115fb565b8160000160189054906101000a900467ffffffffffffffff165b8260020160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b6000816116665761163683611fc4565b8360010160009054906101000a90046fffffffffffffffffffffffffffffffff166116619190613c1f565b611688565b8260010160009054906101000a90046fffffffffffffffffffffffffffffffff165b9050806fffffffffffffffffffffffffffffffff166000808282546116ad91906132e6565b9250508190555060018360020160086101000a81548160ff021916908315150217905550837fc27a46a60d5d211f8ef42242a25d5db8357aefb1bd0e7d8fbab00d4c40d4d1c760405160405180910390a250505050565b60016020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900460ff16908060000160159054906101000a900460ff16908060000160169054906101000a900461ffff16908060000160189054906101000a900467ffffffffffffffff16908060010160009054906101000a90046fffffffffffffffffffffffffffffffff16908060010160109054906101000a90046fffffffffffffffffffffffffffffffff16908060020160009054906101000a900467ffffffffffffffff16908060020160089054906101000a900460ff16905089565b7f0000000000000000000000008cf60b289f8d31f737049b590b5e4285ff0bd1d173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611895576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161188c90613506565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000653b8a2067ffffffffffffffff164211611901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118f890613c9f565b60405180910390fd5b600061190b610eb2565b905060008111611950576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161194790613d0b565b60405180910390fd5b7f0000000000000000000000005afe3855358e112b5647b952709e6165e1c1eeee73ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b81526004016119ab929190613d2b565b6020604051808303816000875af11580156119ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ee9190612f05565b611a2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a24906135de565b60405180910390fd5b5050565b7f00000000000000000000000000000000000000000000000000000000653b8a2067ffffffffffffffff16421115611a9e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a9590613dc6565b60405180910390fd5b6000801b6002541415611ae6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611add90613e32565b60405180910390fd5b6000611af73388600089898961222d565b9050611b47838380806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050600254836126cd565b611b86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b7d90613e9e565b60405180910390fd5b50505050505050565b6000806000600160008581526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611c3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c349061364a565b60405180910390fd5b611c4681611fc4565b92508060010160109054906101000a90046fffffffffffffffffffffffffffffffff16915050915091565b7f0000000000000000000000008cf60b289f8d31f737049b590b5e4285ff0bd1d181565b60025481565b7f0000000000000000000000005afe3855358e112b5647b952709e6165e1c1eeee81565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611d30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d2790613f0a565b60405180910390fd5b60006001600086815260200190815260200160002090503373ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611dd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd090613f9c565b60405180910390fd5b60008160010160109054906101000a90046fffffffffffffffffffffffffffffffff16611e0583611fc4565b611e0f9190613c1f565b90506fffffffffffffffffffffffffffffffff8016846fffffffffffffffffffffffffffffffff1614611e425783611e44565b805b9250806fffffffffffffffffffffffffffffffff16836fffffffffffffffffffffffffffffffff161115611ead576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea490614008565b60405180910390fd5b826fffffffffffffffffffffffffffffffff16600080828254611ed091906132e6565b92505081905550828260010160108282829054906101000a90046fffffffffffffffffffffffffffffffff16611f069190614028565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055508473ffffffffffffffffffffffffffffffffffffffff168260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16877f31b718389b1eb92df83ab00c1a5112e5bb8a02c7c1c9c02e1e3c15ad33e0532660405160405180910390a450509392505050565b6000428260000160189054906101000a900467ffffffffffffffff1667ffffffffffffffff16111561202b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612022906140ba565b60405180910390fd5b6000603c80601860078660000160169054906101000a900461ffff1661ffff1661205591906140da565b61205f91906140da565b61206991906140da565b61207391906140da565b90506000808460020160009054906101000a900467ffffffffffffffff1667ffffffffffffffff16116120c9578360000160189054906101000a900467ffffffffffffffff16426120c49190613866565b612106565b8360000160189054906101000a900467ffffffffffffffff168460020160009054906101000a900467ffffffffffffffff166121059190613866565b5b90508167ffffffffffffffff168167ffffffffffffffff161061214b578360010160009054906101000a90046fffffffffffffffffffffffffffffffff169250612226565b60008460000160149054906101000a900460ff1660ff16141561219a576121938460010160009054906101000a90046fffffffffffffffffffffffffffffffff1682846126e4565b9250612225565b60018460000160149054906101000a900460ff1660ff1614156121e9576121e28460010160009054906101000a90046fffffffffffffffffffffffffffffffff168284612786565b9250612224565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161221b90614168565b60405180910390fd5b5b5b5050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16141561229e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612295906141d4565b60405180910390fd5b60028660ff16106122e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122db90614240565b60405180910390fd5b6122f2878787878787611256565b9050600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612399576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612390906142ac565b60405180910390fd5b60006123a3610eb2565b9050826fffffffffffffffffffffffffffffffff168110156123fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123f190614318565b60405180910390fd5b826fffffffffffffffffffffffffffffffff1660008082825461241d91906133ac565b925050819055506040518061012001604052808973ffffffffffffffffffffffffffffffffffffffff1681526020018860ff16815260200187151581526020018661ffff1681526020018567ffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff168152602001600015158152506001600084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff021916908360ff16021790555060408201518160000160156101000a81548160ff02191690831515021790555060608201518160000160166101000a81548161ffff021916908361ffff16021790555060808201518160000160186101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060a08201518160010160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160010160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060e08201518160020160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101008201518160020160086101000a81548160ff0219169083151502179055509050508773ffffffffffffffffffffffffffffffffffffffff16827fff2781f5af6cf115d187dd0e4ef590f5d1288b83ef3eb6739c69db99e70c8b4d60405160405180910390a3509695505050505050565b6000826126da8584612852565b1490509392505050565b6000808267ffffffffffffffff168467ffffffffffffffff16866fffffffffffffffffffffffffffffffff1661271a9190614338565b61272491906143c1565b90506fffffffffffffffffffffffffffffffff801681111561277b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127729061443e565b60405180910390fd5b809150509392505050565b6000808267ffffffffffffffff168367ffffffffffffffff166127a99190614338565b8467ffffffffffffffff168567ffffffffffffffff16876fffffffffffffffffffffffffffffffff166127dc9190614338565b6127e69190614338565b6127f091906143c1565b90506fffffffffffffffffffffffffffffffff8016811115612847576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161283e9061443e565b60405180910390fd5b809150509392505050565b60008082905060005b84518110156128bc5760008582815181106128795761287861445e565b5b6020026020010151905080831161289b5761289483826128c7565b92506128a8565b6128a581846128c7565b92505b5080806128b49061448d565b91505061285b565b508091505092915050565b600082600052816020526040600020905092915050565b600080fd5b600080fd5b6000819050919050565b6128fb816128e8565b811461290657600080fd5b50565b600081359050612918816128f2565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006129498261291e565b9050919050565b6129598161293e565b811461296457600080fd5b50565b60008135905061297681612950565b92915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b6129a18161297c565b81146129ac57600080fd5b50565b6000813590506129be81612998565b92915050565b6000806000606084860312156129dd576129dc6128de565b5b60006129eb86828701612909565b93505060206129fc86828701612967565b9250506040612a0d868287016129af565b9150509250925092565b6000819050919050565b612a2a81612a17565b82525050565b6000602082019050612a456000830184612a21565b92915050565b600060208284031215612a6157612a606128de565b5b6000612a6f84828501612909565b91505092915050565b600060ff82169050919050565b612a8e81612a78565b8114612a9957600080fd5b50565b600081359050612aab81612a85565b92915050565b60008115159050919050565b612ac681612ab1565b8114612ad157600080fd5b50565b600081359050612ae381612abd565b92915050565b600061ffff82169050919050565b612b0081612ae9565b8114612b0b57600080fd5b50565b600081359050612b1d81612af7565b92915050565b600067ffffffffffffffff82169050919050565b612b4081612b23565b8114612b4b57600080fd5b50565b600081359050612b5d81612b37565b92915050565b60008060008060008060c08789031215612b8057612b7f6128de565b5b6000612b8e89828a01612967565b9650506020612b9f89828a01612a9c565b9550506040612bb089828a01612ad4565b9450506060612bc189828a01612b0e565b9350506080612bd289828a01612b4e565b92505060a0612be389828a016129af565b9150509295509295509295565b612bf9816128e8565b82525050565b6000602082019050612c146000830184612bf0565b92915050565b612c2381612b23565b82525050565b6000602082019050612c3e6000830184612c1a565b92915050565b612c4d8161293e565b82525050565b612c5c81612a78565b82525050565b612c6b81612ab1565b82525050565b612c7a81612ae9565b82525050565b612c898161297c565b82525050565b600061012082019050612ca5600083018c612c44565b612cb2602083018b612c53565b612cbf604083018a612c62565b612ccc6060830189612c71565b612cd96080830188612c1a565b612ce660a0830187612c80565b612cf360c0830186612c80565b612d0060e0830185612c1a565b612d0e610100830184612c62565b9a9950505050505050505050565b600060208284031215612d3257612d316128de565b5b6000612d4084828501612967565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f840112612d6e57612d6d612d49565b5b8235905067ffffffffffffffff811115612d8b57612d8a612d4e565b5b602083019150836020820283011115612da757612da6612d53565b5b9250929050565b60008060008060008060a08789031215612dcb57612dca6128de565b5b6000612dd989828a01612a9c565b9650506020612dea89828a01612b0e565b9550506040612dfb89828a01612b4e565b9450506060612e0c89828a016129af565b935050608087013567ffffffffffffffff811115612e2d57612e2c6128e3565b5b612e3989828a01612d58565b92509250509295509295509295565b6000604082019050612e5d6000830185612c80565b612e6a6020830184612c80565b9392505050565b6000602082019050612e866000830184612c44565b92915050565b6000819050919050565b6000612eb1612eac612ea78461297c565b612e8c565b612a17565b9050919050565b612ec181612e96565b82525050565b6000604082019050612edc6000830185612c44565b612ee96020830184612eb8565b9392505050565b600081519050612eff81612abd565b92915050565b600060208284031215612f1b57612f1a6128de565b5b6000612f2984828501612ef0565b91505092915050565b600082825260208201905092915050565b7f436f756c64206e6f7420617070726f766520746f6b656e730000000000000000600082015250565b6000612f79601883612f32565b9150612f8482612f43565b602082019050919050565b60006020820190508181036000830152612fa881612f6c565b9050919050565b612fb881612a17565b8114612fc357600080fd5b50565b600081519050612fd581612faf565b92915050565b600060208284031215612ff157612ff06128de565b5b6000612fff84828501612fc6565b91505092915050565b600060608201905061301d6000830186612c44565b61302a6020830185612c44565b6130376040830184612c80565b949350505050565b6000819050919050565b600061306461305f61305a8461303f565b612e8c565b612a17565b9050919050565b61307481613049565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b838110156130b4578082015181840152602081019050613099565b838111156130c3576000848401525b50505050565b6000601f19601f8301169050919050565b60006130e58261307a565b6130ef8185613085565b93506130ff818560208601613096565b613108816130c9565b840191505092915050565b600061312e6131296131248461303f565b612e8c565b612a78565b9050919050565b61313e81613113565b82525050565b60006080820190506131596000830187612c44565b613166602083018661306b565b818103604083015261317881856130da565b90506131876060830184613135565b95945050505050565b7f4d6f64756c65207472616e73616374696f6e206661696c656400000000000000600082015250565b60006131c6601983612f32565b91506131d182613190565b602082019050919050565b600060208201905081810360008301526131f5816131b9565b9050919050565b60006040820190506132116000830185612c44565b61321e602083018461306b565b9392505050565b7f436f756c64206e6f742073657420746f6b656e20616c6c6f77616e636520746f60008201527f2030000000000000000000000000000000000000000000000000000000000000602082015250565b6000613281602283612f32565b915061328c82613225565b604082019050919050565b600060208201905081810360008301526132b081613274565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006132f182612a17565b91506132fc83612a17565b92508282101561330f5761330e6132b7565b5b828203905092915050565b7f436f756c64206e6f742064656475637420746f6b656e732066726f6d20706f6f60008201527f6c00000000000000000000000000000000000000000000000000000000000000602082015250565b6000613376602183612f32565b91506133818261331a565b604082019050919050565b600060208201905081810360008301526133a581613369565b9050919050565b60006133b782612a17565b91506133c283612a17565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156133f7576133f66132b7565b5b828201905092915050565b7f436f756c64206e6f742061646420746f6b656e7320746f2062656e656669636960008201527f6172790000000000000000000000000000000000000000000000000000000000602082015250565b600061345e602383612f32565b915061346982613402565b604082019050919050565b6000602082019050818103600083015261348d81613451565b9050919050565b7f43616e206f6e6c792062652063616c6c656420627920706f6f6c206d616e616760008201527f6572000000000000000000000000000000000000000000000000000000000000602082015250565b60006134f0602283612f32565b91506134fb82613494565b604082019050919050565b6000602082019050818103600083015261351f816134e3565b9050919050565b7f537461746520726f6f7420616c726561647920696e697469616c697a65640000600082015250565b600061355c601e83612f32565b915061356782613526565b602082019050919050565b6000602082019050818103600083015261358b8161354f565b9050919050565b7f546f6b656e207472616e73666572206661696c65640000000000000000000000600082015250565b60006135c8601583612f32565b91506135d382613592565b602082019050919050565b600060208201905081810360008301526135f7816135bb565b9050919050565b7f56657374696e67206e6f7420666f756e64000000000000000000000000000000600082015250565b6000613634601183612f32565b915061363f826135fe565b602082019050919050565b6000602082019050818103600083015261366381613627565b9050919050565b7f4f6e6c79206d616e616765642076657374696e67732063616e2062652070617560008201527f7365640000000000000000000000000000000000000000000000000000000000602082015250565b60006136c6602383612f32565b91506136d18261366a565b604082019050919050565b600060208201905081810360008301526136f5816136b9565b9050919050565b7f56657374696e6720616c72656164792070617573656400000000000000000000600082015250565b6000613732601683612f32565b915061373d826136fc565b602082019050919050565b6000602082019050818103600083015261376181613725565b9050919050565b7f56657374696e67206973206e6f74207061757365640000000000000000000000600082015250565b600061379e601583612f32565b91506137a982613768565b602082019050919050565b600060208201905081810360008301526137cd81613791565b9050919050565b7f56657374696e6720686173206265656e2063616e63656c6c656420616e64206360008201527f616e6e6f7420626520756e706175736564000000000000000000000000000000602082015250565b6000613830603183612f32565b915061383b826137d4565b604082019050919050565b6000602082019050818103600083015261385f81613823565b9050919050565b600061387182612b23565b915061387c83612b23565b92508282101561388f5761388e6132b7565b5b828203905092915050565b60006138a582612b23565b91506138b083612b23565b92508267ffffffffffffffff038211156138cd576138cc6132b7565b5b828201905092915050565b60006138f36138ee6138e98461291e565b612e8c565b61291e565b9050919050565b6000613905826138d8565b9050919050565b6000613917826138fa565b9050919050565b6139278161390c565b82525050565b60006060820190506139426000830186612bf0565b61394f6020830185612a21565b61395c604083018461391e565b949350505050565b600060e082019050613979600083018a612bf0565b6139866020830189612c44565b6139936040830188612c53565b6139a06060830187612c62565b6139ad6080830186612c71565b6139ba60a0830185612c1a565b6139c760c0830184612c80565b98975050505050505050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b613a1a613a15826139d3565b6139ff565b82525050565b6000819050919050565b613a3b613a36826128e8565b613a20565b82525050565b6000613a4d8287613a09565b600182019150613a5d8286613a09565b600182019150613a6d8285613a2a565b602082019150613a7d8284613a2a565b60208201915081905095945050505050565b7f54686973206d6574686f64206973206e6f7420617661696c61626c6520666f7260008201527f207468697320636f6e7472616374000000000000000000000000000000000000602082015250565b6000613aeb602e83612f32565b9150613af682613a8f565b604082019050919050565b60006020820190508181036000830152613b1a81613ade565b9050919050565b7f4f6e6c79206d616e616765642076657374696e67732063616e2062652063616e60008201527f63656c6c65640000000000000000000000000000000000000000000000000000602082015250565b6000613b7d602683612f32565b9150613b8882613b21565b604082019050919050565b60006020820190508181036000830152613bac81613b70565b9050919050565b7f56657374696e6720616c72656164792063616e63656c6c656400000000000000600082015250565b6000613be9601983612f32565b9150613bf482613bb3565b602082019050919050565b60006020820190508181036000830152613c1881613bdc565b9050919050565b6000613c2a8261297c565b9150613c358361297c565b925082821015613c4857613c476132b7565b5b828203905092915050565b7f546f6b656e732063616e207374696c6c2062652072656465656d656400000000600082015250565b6000613c89601c83612f32565b9150613c9482613c53565b602082019050919050565b60006020820190508181036000830152613cb881613c7c565b9050919050565b7f4e6f20746f6b656e7320746f20636c61696d0000000000000000000000000000600082015250565b6000613cf5601283612f32565b9150613d0082613cbf565b602082019050919050565b60006020820190508181036000830152613d2481613ce8565b9050919050565b6000604082019050613d406000830185612c44565b613d4d6020830184612a21565b9392505050565b7f446561646c696e6520746f2072656465656d2076657374696e6720686173206260008201527f65656e2065786365656465640000000000000000000000000000000000000000602082015250565b6000613db0602c83612f32565b9150613dbb82613d54565b604082019050919050565b60006020820190508181036000830152613ddf81613da3565b9050919050565b7f537461746520726f6f74206e6f7420696e697469616c697a6564000000000000600082015250565b6000613e1c601a83612f32565b9150613e2782613de6565b602082019050919050565b60006020820190508181036000830152613e4b81613e0f565b9050919050565b7f496e76616c6964206d65726b6c652070726f6f66000000000000000000000000600082015250565b6000613e88601483612f32565b9150613e9382613e52565b602082019050919050565b60006020820190508181036000830152613eb781613e7b565b9050919050565b7f43616e6e6f7420636c61696d20746f20302d6164647265737300000000000000600082015250565b6000613ef4601983612f32565b9150613eff82613ebe565b602082019050919050565b60006020820190508181036000830152613f2381613ee7565b9050919050565b7f43616e206f6e6c7920626520636c61696d65642062792076657374696e67206f60008201527f776e657200000000000000000000000000000000000000000000000000000000602082015250565b6000613f86602483612f32565b9150613f9182613f2a565b604082019050919050565b60006020820190508181036000830152613fb581613f79565b9050919050565b7f547279696e6720746f20636c61696d20746f6f206d616e7920746f6b656e7300600082015250565b6000613ff2601f83612f32565b9150613ffd82613fbc565b602082019050919050565b6000602082019050818103600083015261402181613fe5565b9050919050565b60006140338261297c565b915061403e8361297c565b9250826fffffffffffffffffffffffffffffffff03821115614063576140626132b7565b5b828201905092915050565b7f56657374696e67206e6f74206163746976652079657400000000000000000000600082015250565b60006140a4601683612f32565b91506140af8261406e565b602082019050919050565b600060208201905081810360008301526140d381614097565b9050919050565b60006140e582612b23565b91506140f083612b23565b92508167ffffffffffffffff0483118215151615614111576141106132b7565b5b828202905092915050565b7f496e76616c696420637572766520747970650000000000000000000000000000600082015250565b6000614152601283612f32565b915061415d8261411c565b602082019050919050565b6000602082019050818103600083015261418181614145565b9050919050565b7f496e76616c6964206163636f756e740000000000000000000000000000000000600082015250565b60006141be600f83612f32565b91506141c982614188565b602082019050919050565b600060208201905081810360008301526141ed816141b1565b9050919050565b7f496e76616c69642076657374696e672063757276650000000000000000000000600082015250565b600061422a601583612f32565b9150614235826141f4565b602082019050919050565b600060208201905081810360008301526142598161421d565b9050919050565b7f56657374696e6720696420616c72656164792075736564000000000000000000600082015250565b6000614296601783612f32565b91506142a182614260565b602082019050919050565b600060208201905081810360008301526142c581614289565b9050919050565b7f4e6f7420656e6f75676820746f6b656e7320617661696c61626c650000000000600082015250565b6000614302601b83612f32565b915061430d826142cc565b602082019050919050565b60006020820190508181036000830152614331816142f5565b9050919050565b600061434382612a17565b915061434e83612a17565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614387576143866132b7565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006143cc82612a17565b91506143d783612a17565b9250826143e7576143e6614392565b5b828204905092915050565b7f4f766572666c6f7720696e2063757276652063616c63756c6174696f6e000000600082015250565b6000614428601d83612f32565b9150614433826143f2565b602082019050919050565b600060208201905081810360008301526144578161441b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061449882612a17565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156144cb576144ca6132b7565b5b60018201905091905056fea26469706673582212206a664b96257ad5799280f460892727de299cf9f1bc6dec88875c5eba48a695e764736f6c634300080b0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.