ETH Price: $2,358.47 (-0.53%)

Contract

0x71b102Ae6DEA02cdc43dbEEB0AcffF225C81Ef96

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Withdraw Mul2977798782025-01-21 14:58:55376 days ago1737471535IN
0x71b102Ae...25C81Ef96
0 ETH0.000003290.027371
Withdraw Mul2918034272025-01-04 6:03:34394 days ago1735970614IN
0x71b102Ae...25C81Ef96
0 ETH0.000001510.01
Withdraw Mul2882914652024-12-25 0:59:52404 days ago1735088392IN
0x71b102Ae...25C81Ef96
0 ETH0.000001930.01
Withdraw Mul2720222092024-11-07 15:48:05451 days ago1730994485IN
0x71b102Ae...25C81Ef96
0 ETH0.00000240.010922
Withdraw Mul2716251412024-11-06 12:04:07453 days ago1730894647IN
0x71b102Ae...25C81Ef96
0 ETH0.000001920.01
Withdraw Mul2709745342024-11-04 14:36:38455 days ago1730730998IN
0x71b102Ae...25C81Ef96
0 ETH0.000002560.01
Withdraw Mul2699315592024-11-01 13:48:25458 days ago1730468905IN
0x71b102Ae...25C81Ef96
0 ETH0.00000310.020784
Withdraw Mul2696931742024-10-31 21:10:40458 days ago1730409040IN
0x71b102Ae...25C81Ef96
0 ETH0.000001740.01
Withdraw Mul2657357782024-10-20 8:58:40470 days ago1729414720IN
0x71b102Ae...25C81Ef96
0 ETH0.000001560.01
Withdraw Mul2514674672024-09-08 19:22:57511 days ago1725823377IN
0x71b102Ae...25C81Ef96
0 ETH0.000000940.01
Withdraw Mul2359370422024-07-25 14:59:30556 days ago1721919570IN
0x71b102Ae...25C81Ef96
0 ETH0.000001210.011041
Withdraw Mul2339347482024-07-19 19:25:02562 days ago1721417102IN
0x71b102Ae...25C81Ef96
0 ETH0.000001790.01584
Withdraw Mul2334782212024-07-18 11:33:20564 days ago1721302400IN
0x71b102Ae...25C81Ef96
0 ETH0.000001610.010785
Withdraw Mul2334252712024-07-18 7:39:29564 days ago1721288369IN
0x71b102Ae...25C81Ef96
0 ETH0.000004350.025843
Withdraw Mul2333036642024-07-17 23:06:50564 days ago1721257610IN
0x71b102Ae...25C81Ef96
0 ETH0.000001510.01
Withdraw Mul2330575522024-07-17 5:59:19565 days ago1721195959IN
0x71b102Ae...25C81Ef96
0 ETH0.000002090.01
Withdraw Mul2305080282024-07-09 20:31:04572 days ago1720557064IN
0x71b102Ae...25C81Ef96
0 ETH0.000001290.01
Withdraw Mul2220978052024-06-15 11:30:14597 days ago1718451014IN
0x71b102Ae...25C81Ef96
0 ETH0.000001120.01
Withdraw Mul2220977392024-06-15 11:29:57597 days ago1718450997IN
0x71b102Ae...25C81Ef96
0 ETH0.000000940.01
Withdraw Mul2220976832024-06-15 11:29:43597 days ago1718450983IN
0x71b102Ae...25C81Ef96
0 ETH0.000000940.01
Withdraw Mul2220976192024-06-15 11:29:27597 days ago1718450967IN
0x71b102Ae...25C81Ef96
0 ETH0.000000940.01
Withdraw Mul2220975472024-06-15 11:29:09597 days ago1718450949IN
0x71b102Ae...25C81Ef96
0 ETH0.000000940.01
Withdraw Mul2220974702024-06-15 11:28:49597 days ago1718450929IN
0x71b102Ae...25C81Ef96
0 ETH0.000000940.01
Withdraw Mul2220973732024-06-15 11:28:25597 days ago1718450905IN
0x71b102Ae...25C81Ef96
0 ETH0.000001120.01
Withdraw Mul2217173992024-06-14 9:05:12598 days ago1718355912IN
0x71b102Ae...25C81Ef96
0 ETH0.000003340.01
View all transactions

Parent Transaction Hash Block From To
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RewardDistributor

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
london EvmVersion
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "./libraries/TransferHelper.sol";
import "./common/Adminable.sol";
import "./common/ReentrancyGuard.sol";
import "./interface/IXOLE.sol";
import "./interface/IUniV2ClassPair.sol";

contract RewardDistributor is Adminable, ReentrancyGuard {
    using TransferHelper for IERC20;
    using TransferHelper for IUniV2ClassPair;

    error InvalidAmount();
    error InvalidTime();
    error InvalidPenalty();
    error InsufficientTransfersIn();
    error NotStarted();
    error Expired();
    error NotExpired();
    error AlreadyRecycled();
    error AlreadyVested();
    error IncorrectMerkleProof();
    error ExceedMax(uint256 amount);

    struct Epoch {
        bytes32 merkleRoot;
        uint256 total;
        uint256 vested;
        uint256 startTime; // vest start time
        uint256 expireTime; // vest expire time
        uint256 vestDuration; // vest duration, in seconds
        uint16 penaltyBase; // exit penalty base percentage, 2000 => 20%
        uint16 penaltyAdd; // exit penalty add percentage, 6000 => 60%
        bool recycled;
    }

    struct Reward {
        uint256 amount; // total amount to be vested
        uint256 withdrawn; // withdrawn amount by the user
        uint256 vestStartTime; // vest start time
    }

    uint256 internal constant PERCENT_DIVISOR = 10000;
    uint256 private constant WEEK = 7 * 86400;  // XOLE lock times are rounded by week
    uint256 private constant MIN_DURATION = 7 * 86400;  // 7 days
    uint256 private constant MAX_DURATION = 4 * 365 * 86400;  // 4 years

    IERC20 public immutable oleToken;
    IUniV2ClassPair public immutable pair;
    address public immutable token1;  // token1 of lp
    address public immutable xole;
    uint256 public epochIdx;
    uint256 public minXOLELockDuration; // min XOLE lock duration in seconds when converting
    uint256 public withdrawablePenalty; // the withdrawable penalty for admin

    // mapping of epochId, user to reward info
    mapping(uint256 => mapping(address => Reward)) public rewards;
    // mapping of epochId to epoch info
    mapping(uint256 => Epoch) public epochs;

    constructor(address _oleToken, address _pair, address _token1, address _xole, uint256 _minXOLELockDuration) verifyDuration(_minXOLELockDuration){
        oleToken = IERC20(_oleToken);
        pair = IUniV2ClassPair(_pair);
        token1 = _token1;
        xole = _xole;
        minXOLELockDuration = _minXOLELockDuration;
        admin = payable(msg.sender);
    }

    event VestStarted(uint256 epochId, address account, uint256 balance, uint256 vestTime);
    event Withdrawn(uint256 epochId, address account, uint256 amount, uint256 penalty);
    event ConvertedToXOLE(uint256 epochId, address account, uint256 amount);

    event EpochAdded(uint256 epochId, bytes32 merkleRoot, uint256 total, uint256 startTime, uint256 expireTime, uint256 vestDuration, uint16 penaltyBase, uint16 penaltyAdd);
    event Recycled(uint256 epochId, uint256 recycledAmount);
    event PenaltyWithdrawn(uint256 amount);

    function vest(uint256 _epochId, uint256 _balance, bytes32[] calldata _merkleProof) external {
        Epoch storage epoch = epochs[_epochId];
        if (block.timestamp < epoch.startTime) revert NotStarted();
        if (block.timestamp > epoch.expireTime) revert Expired();
        if (_balance == 0 || _balance + epoch.vested > epoch.total) revert InvalidAmount();

        Reward memory reward = rewards[_epochId][msg.sender];
        if (reward.amount > 0) revert AlreadyVested();
        if (!_verifyVest(msg.sender, epoch.merkleRoot, _balance, _merkleProof)) revert IncorrectMerkleProof();
        epoch.vested += _balance;
        rewards[_epochId][msg.sender] = Reward(_balance, 0, block.timestamp);
        emit VestStarted(_epochId, msg.sender, _balance, block.timestamp);
    }

    function withdrawMul(uint256[] calldata _epochIds) external {
        uint256 total;
        for (uint256 i = 0; i < _epochIds.length; i++) {
            total += _withdrawReward(_epochIds[i]);
        }
        oleToken.safeTransfer(msg.sender, total);
    }

    function withdraw(uint256 epochId) external {
        uint256 withdrawing = _withdrawReward(epochId);
        oleToken.safeTransfer(msg.sender, withdrawing);
    }

    function earlyExit(uint256 epochId) external {
        Reward storage reward = rewards[epochId][msg.sender];
        if (reward.amount == 0 || reward.amount == reward.withdrawn) revert InvalidAmount();
        (uint256 withdrawable, uint256 penalty) = _earlyExitWithdrawable(reward, epochId);
        reward.withdrawn = reward.amount;
        withdrawablePenalty += penalty;
        emit Withdrawn(epochId, msg.sender, withdrawable, penalty);
        oleToken.safeTransfer(msg.sender, withdrawable);
    }

    /// @param token1MaxAmount, The token1 max supply amount when adding liquidity
    /// @param unlockTime, The unlock time for the XOLE lock
    function convertToNewXole(uint256 epochId, uint256 token1MaxAmount, uint256 unlockTime) external nonReentrant {
        uint256 conversion = _convertOLE(epochId, msg.sender);
        _convertToNewXole(msg.sender, conversion, token1MaxAmount, unlockTime);
    }

    function convertToNewXoleForOthers(uint256 epochId, address account, uint256 token1MaxAmount, uint256 unlockTime) external nonReentrant {
        uint256 conversion = _convertOLE(epochId, msg.sender);
        _convertToNewXole(account, conversion, token1MaxAmount, unlockTime);
    }

    function convertAndIncreaseXoleAmount(uint256 epochId, uint256 token1MaxAmount) external nonReentrant {
        uint256 conversion = _convertOLE(epochId, msg.sender);
        _convertAndIncreaseXoleAmount(msg.sender, conversion, token1MaxAmount);
    }

    function convertAndIncreaseXoleAmountForOthers(uint256 epochId, address account, uint256 token1MaxAmount) external nonReentrant {
        uint256 conversion = _convertOLE(epochId, msg.sender);
        _convertAndIncreaseXoleAmount(account, conversion, token1MaxAmount);
    }

    /*** View Functions ***/
    function verifyVest(address account, uint256 _epochId, uint256 _balance, bytes32[] calldata _merkleProof) external view returns (bool valid){
        return _verifyVest(account, epochs[_epochId].merkleRoot, _balance, _merkleProof);
    }

    function getWithdrawable(address account, uint256[] calldata _epochIds) external view returns (uint256[] memory results){
        uint256 len = _epochIds.length;
        results = new uint256[](len);
        for (uint256 i = 0; i < len; i++) {
            Reward memory reward = rewards[_epochIds[i]][account];
            if (reward.amount == reward.withdrawn) {
                results[i] = 0;
                continue;
            }
            Epoch memory epoch = epochs[_epochIds[i]];
            uint256 releaseAble = _releaseable(reward, epoch);
            results[i] = releaseAble - reward.withdrawn;
        }
    }

    function getEarlyExitWithdrawable(address account, uint256 _epochId) external view returns (uint256 amount, uint256 penalty){
        Reward memory reward = rewards[_epochId][account];
        if (reward.amount == reward.withdrawn) {
            (amount, penalty) = (0, 0);
        } else {
            (amount, penalty) = _earlyExitWithdrawable(reward, _epochId);
        }
    }

    /*** Admin Functions ***/
    function newEpoch(
        bytes32 merkleRoot,
        uint256 total,
        uint256 startTime,
        uint256 expireTime,
        uint256 vestDuration,
        uint16 penaltyBase,
        uint16 penaltyAdd)
    external onlyAdminOrDeveloper verifyDuration(vestDuration) {
        if (expireTime <= startTime || expireTime <= block.timestamp) revert InvalidTime();
        if (total == 0 || penaltyBase + penaltyAdd >= PERCENT_DIVISOR) revert InvalidAmount();
        uint256 received = oleToken.safeTransferFrom(msg.sender, address(this), total);
        if(received != total) revert InsufficientTransfersIn();
        uint256 epochId = ++epochIdx;
        epochs[epochId] = Epoch(merkleRoot, total, 0, startTime, expireTime, vestDuration, penaltyBase, penaltyAdd, false);
        emit EpochAdded(epochId, merkleRoot, total, startTime, expireTime, vestDuration, penaltyBase, penaltyAdd);
    }

    function recycle(uint256[] calldata _epochIds) external onlyAdmin {
        uint256 total;
        for (uint256 i = 0; i < _epochIds.length; i++) {
            Epoch storage epoch = epochs[_epochIds[i]];
            if (epoch.recycled) revert AlreadyRecycled();
            if (block.timestamp <= epoch.expireTime) revert NotExpired();
            uint256 recycleAmount = epoch.total - epoch.vested;
            total += recycleAmount;
            epoch.recycled = true;
            emit Recycled(_epochIds[i], recycleAmount);
        }
        if (total == 0) revert InvalidAmount();
        oleToken.safeTransfer(admin, total);
    }

    function withdrawPenalty() external onlyAdmin {
        if (withdrawablePenalty == 0) revert InvalidAmount();
        uint256 _withdrawablePenalty = withdrawablePenalty;
        withdrawablePenalty = 0;
        oleToken.safeTransfer(admin, _withdrawablePenalty);
        emit PenaltyWithdrawn(_withdrawablePenalty);
    }

    function setMinXOLELockDuration(uint256 _minXOLELockDuration) external onlyAdmin verifyDuration(_minXOLELockDuration) {
        minXOLELockDuration = _minXOLELockDuration;
    }

    /*** Internal Functions ***/
    function _verifyVest(address account, bytes32 root, uint256 _balance, bytes32[] memory _merkleProof) internal pure returns (bool valid) {
        bytes32 leaf = keccak256(abi.encodePacked(account, _balance));
        return MerkleProof.verify(_merkleProof, root, leaf);
    }

    function _withdrawReward(uint256 epochId) internal returns (uint256){
        Reward storage reward = rewards[epochId][msg.sender];
        if (reward.amount == 0 || reward.amount == reward.withdrawn) revert InvalidAmount();
        Epoch memory epoch = epochs[epochId];
        uint256 withdrawing = _releaseable(reward, epoch) - reward.withdrawn;
        if (withdrawing == 0) revert InvalidAmount();
        reward.withdrawn += withdrawing;
        emit Withdrawn(epochId, msg.sender, withdrawing, 0);
        return withdrawing;
    }

    function _releaseable(Reward memory reward, Epoch memory epoch) internal view returns (uint256) {
        uint256 endTime = reward.vestStartTime + epoch.vestDuration;
        if (block.timestamp > endTime) {
            return reward.amount;
        } else {
            return (block.timestamp - reward.vestStartTime) * reward.amount / epoch.vestDuration;
        }
    }

    function _earlyExitWithdrawable(Reward memory reward, uint256 epochId) internal view returns (uint256 withdrawable, uint256 penalty) {
        Epoch memory epoch = epochs[epochId];
        uint256 releaseable = _releaseable(reward, epoch);
        withdrawable = releaseable - reward.withdrawn;
        // cal penalty
        uint256 endTime = reward.vestStartTime + epoch.vestDuration;
        uint256 penaltyFactor = (endTime - block.timestamp) * epoch.penaltyAdd / epoch.vestDuration + epoch.penaltyBase;
        uint256 locked = reward.amount - releaseable;
        penalty = locked * penaltyFactor / PERCENT_DIVISOR;
        if (penalty >= locked) revert InvalidPenalty();
        withdrawable += locked - penalty;
        return (withdrawable, penalty);
    }

    function _convertOLE(uint256 epochId, address account) internal returns (uint256) {
        Reward storage reward = rewards[epochId][account];
        uint256 convertible = reward.amount - reward.withdrawn;
        if (reward.amount == 0 || convertible == 0) revert InvalidAmount();
        reward.withdrawn = reward.amount;
        emit ConvertedToXOLE(epochId, account, convertible);
        return convertible;
    }

    function _convertToNewXole(address account, uint256 oleAmount, uint256 token1MaxAmount, uint256 unlockTime) internal {
        unlockTime = unlockTime / WEEK * WEEK;
        verifyUnlockTime(unlockTime);
        uint256 liquidity = formLp(oleAmount, token1MaxAmount);
        pair.safeApprove(xole, liquidity);
        IXOLE(xole).create_lock_for(account, liquidity, unlockTime);
    }

    function _convertAndIncreaseXoleAmount(address account, uint256 oleAmount, uint256 token1MaxAmount) internal {
        (,uint256 lockTime) = IXOLE(xole).locked(account);
        verifyUnlockTime(lockTime);
        uint256 liquidity = formLp(oleAmount, token1MaxAmount);
        pair.safeApprove(xole, liquidity);
        IXOLE(xole).increase_amount_for(account, liquidity);
    }

    function formLp(uint256 oleAmount, uint256 token1MaxAmount) internal returns (uint256 liquidity){
        (uint256 reserveA, uint256 reserveB) = getReserves(address(oleToken), token1);
        uint256 amountBOptimal = oleAmount * reserveB / reserveA;
        if (amountBOptimal > token1MaxAmount) revert ExceedMax(amountBOptimal);
        IERC20(token1).safeTransferFrom(msg.sender, address(pair), amountBOptimal);
        oleToken.safeTransfer(address(pair), oleAmount);
        liquidity = pair.mint(address(this));
    }

    function getReserves(address tokenA, address tokenB) internal view returns (uint256 reserveA, uint256 reserveB) {
        (uint256 reserve0, uint256 reserve1,) = pair.getReserves();
        (address _token0,) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
        (reserveA, reserveB) = tokenA == _token0 ? (reserve0, reserve1) : (reserve1, reserve0);
    }

    function verifyUnlockTime(uint256 _unlockTime) internal view {
        if (_unlockTime < block.timestamp + minXOLELockDuration || _unlockTime > block.timestamp + MAX_DURATION) revert InvalidTime();
    }

    modifier verifyDuration(uint256 _duration) {
        if (_duration < MIN_DURATION || _duration > MAX_DURATION) revert InvalidTime();
        _;
    }

}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/**
 * @title TransferHelper
 * @dev Wrappers around ERC20 operations that returns the value received by recipent and the actual allowance of approval.
 * To use this library you can add a `using TransferHelper for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library TransferHelper {
    function safeTransfer(
        IERC20 _token,
        address _to,
        uint256 _amount
    ) internal returns (uint256 amountReceived) {
        if (_amount > 0) {
            bool success;
            uint256 balanceBefore = _token.balanceOf(_to);
            (success, ) = address(_token).call(abi.encodeWithSelector(_token.transfer.selector, _to, _amount));
            require(success, "TF");
            uint256 balanceAfter = _token.balanceOf(_to);
            require(balanceAfter > balanceBefore, "TF");
            amountReceived = balanceAfter - balanceBefore;
        }
    }

    function safeTransferFrom(
        IERC20 _token,
        address _from,
        address _to,
        uint256 _amount
    ) internal returns (uint256 amountReceived) {
        if (_amount > 0) {
            bool success;
            uint256 balanceBefore = _token.balanceOf(_to);
            (success, ) = address(_token).call(abi.encodeWithSelector(_token.transferFrom.selector, _from, _to, _amount));
            require(success, "TFF");
            uint256 balanceAfter = _token.balanceOf(_to);
            require(balanceAfter > balanceBefore, "TFF");
            amountReceived = balanceAfter - balanceBefore;
        }
    }

    function safeApprove(
        IERC20 _token,
        address _spender,
        uint256 _amount
    ) internal returns (uint256) {
        bool success;
        if (_token.allowance(address(this), _spender) != 0) {
            (success, ) = address(_token).call(abi.encodeWithSelector(_token.approve.selector, _spender, 0));
            require(success, "AF");
        }
        (success, ) = address(_token).call(abi.encodeWithSelector(_token.approve.selector, _spender, _amount));
        require(success, "AF");

        return _token.allowance(address(this), _spender);
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;

interface IXOLE{

    function create_lock_for(address to, uint256 _value, uint256 _unlock_time) external;

    function increase_amount_for(address to, uint256 _value) external;

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

    function locked(address addr) external view returns (uint256 amount, uint256 lockTime);

}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IUniV2ClassPair is IERC20{

    function mint(address to) external returns (uint liquidity);

    function token0() external view returns (address);

    function token1() external view returns (address);

    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
}

File 5 of 8 : ReentrancyGuard.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity 0.8.17;

contract ReentrancyGuard {
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    modifier nonReentrant() {
        check();
        _status = _ENTERED;

        _;

        _status = _NOT_ENTERED;
    }

    function check() private view {
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
    }
}

// SPDX-License-Identifier: BUSL-1.1

pragma solidity 0.8.17;

abstract contract Adminable {
    address payable public admin;
    address payable public pendingAdmin;
    address payable public developer;

    event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);

    event NewAdmin(address oldAdmin, address newAdmin);

    constructor() {
        developer = payable(msg.sender);
    }

    modifier onlyAdmin() {
        checkAdmin();
        _;
    }
    modifier onlyAdminOrDeveloper() {
        require(msg.sender == admin || msg.sender == developer, "Only admin or dev");
        _;
    }

    function setPendingAdmin(address payable newPendingAdmin) external virtual onlyAdmin {
        // Save current value, if any, for inclusion in log
        address oldPendingAdmin = pendingAdmin;
        // Store pendingAdmin with value newPendingAdmin
        pendingAdmin = newPendingAdmin;
        // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)
        emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);
    }

    function acceptAdmin() external virtual {
        require(msg.sender == pendingAdmin, "Only pendingAdmin");
        // Save current values for inclusion in log
        address oldAdmin = admin;
        address oldPendingAdmin = pendingAdmin;
        // Store admin with value pendingAdmin
        admin = pendingAdmin;
        // Clear the pending value
        pendingAdmin = payable(0);
        emit NewAdmin(oldAdmin, admin);
        emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);
    }

    function checkAdmin() private view {
        require(msg.sender == admin, "caller must be admin");
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The tree and the proofs can be generated using our
 * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
 * You will find a quickstart guide in the readme.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 * OpenZeppelin's JavaScript library generates merkle trees that are safe
 * against this attack out of the box.
 */
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 Calldata version of {verify}
     *
     * _Available since v4.7._
     */
    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle 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++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Calldata version of {processProof}
     *
     * _Available since v4.7._
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * _Available since v4.7._
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofLen = proof.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            require(proofPos == proofLen, "MerkleProof: invalid multiproof");
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Calldata version of {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofLen = proof.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            require(proofPos == proofLen, "MerkleProof: invalid multiproof");
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

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

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_oleToken","type":"address"},{"internalType":"address","name":"_pair","type":"address"},{"internalType":"address","name":"_token1","type":"address"},{"internalType":"address","name":"_xole","type":"address"},{"internalType":"uint256","name":"_minXOLELockDuration","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyRecycled","type":"error"},{"inputs":[],"name":"AlreadyVested","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ExceedMax","type":"error"},{"inputs":[],"name":"Expired","type":"error"},{"inputs":[],"name":"IncorrectMerkleProof","type":"error"},{"inputs":[],"name":"InsufficientTransfersIn","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidPenalty","type":"error"},{"inputs":[],"name":"InvalidTime","type":"error"},{"inputs":[],"name":"NotExpired","type":"error"},{"inputs":[],"name":"NotStarted","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epochId","type":"uint256"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ConvertedToXOLE","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epochId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"total","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expireTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vestDuration","type":"uint256"},{"indexed":false,"internalType":"uint16","name":"penaltyBase","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"penaltyAdd","type":"uint16"}],"name":"EpochAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"NewPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PenaltyWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epochId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"recycledAmount","type":"uint256"}],"name":"Recycled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epochId","type":"uint256"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vestTime","type":"uint256"}],"name":"VestStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epochId","type":"uint256"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"penalty","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochId","type":"uint256"},{"internalType":"uint256","name":"token1MaxAmount","type":"uint256"}],"name":"convertAndIncreaseXoleAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochId","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"token1MaxAmount","type":"uint256"}],"name":"convertAndIncreaseXoleAmountForOthers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochId","type":"uint256"},{"internalType":"uint256","name":"token1MaxAmount","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"name":"convertToNewXole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochId","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"token1MaxAmount","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"name":"convertToNewXoleForOthers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"developer","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochId","type":"uint256"}],"name":"earlyExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"epochIdx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"epochs","outputs":[{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"vested","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"expireTime","type":"uint256"},{"internalType":"uint256","name":"vestDuration","type":"uint256"},{"internalType":"uint16","name":"penaltyBase","type":"uint16"},{"internalType":"uint16","name":"penaltyAdd","type":"uint16"},{"internalType":"bool","name":"recycled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"_epochId","type":"uint256"}],"name":"getEarlyExitWithdrawable","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"penalty","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"_epochIds","type":"uint256[]"}],"name":"getWithdrawable","outputs":[{"internalType":"uint256[]","name":"results","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minXOLELockDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"expireTime","type":"uint256"},{"internalType":"uint256","name":"vestDuration","type":"uint256"},{"internalType":"uint16","name":"penaltyBase","type":"uint16"},{"internalType":"uint16","name":"penaltyAdd","type":"uint16"}],"name":"newEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oleToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"contract IUniV2ClassPair","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_epochIds","type":"uint256[]"}],"name":"recycle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"withdrawn","type":"uint256"},{"internalType":"uint256","name":"vestStartTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minXOLELockDuration","type":"uint256"}],"name":"setMinXOLELockDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newPendingAdmin","type":"address"}],"name":"setPendingAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"_epochId","type":"uint256"},{"internalType":"uint256","name":"_balance","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"verifyVest","outputs":[{"internalType":"bool","name":"valid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_epochId","type":"uint256"},{"internalType":"uint256","name":"_balance","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"vest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_epochIds","type":"uint256[]"}],"name":"withdrawMul","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawPenalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawablePenalty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xole","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

6101006040523480156200001257600080fd5b5060405162002d1e38038062002d1e8339810160408190526200003591620000da565b600280546001600160a01b0319163317905560016003558062093a80811080620000625750630784ce0081115b1562000081576040516337bf561360e11b815260040160405180910390fd5b506001600160a01b0394851660805292841660a05290831660c05290911660e052600555600080546001600160a01b0319163317905562000141565b80516001600160a01b0381168114620000d557600080fd5b919050565b600080600080600060a08688031215620000f357600080fd5b620000fe86620000bd565b94506200010e60208701620000bd565b93506200011e60408701620000bd565b92506200012e60608701620000bd565b9150608086015190509295509295909350565b60805160a05160c05160e051612b106200020e600039600081816101fe01528181611a8d01528181611b4201528181611b8e01528181611cb50152611d080152600081816104cf01528181611fce015261204001526000818161036001528181611b2001528181611c9301528181612063015281816120b8015281816120f301526124550152600081816102e9015281816106e8015281816109d401528181610e5001528181610f78015281816110b20152818161132e01528181611fad01526120960152612b106000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063664c374111610104578063c72a8c95116100a2578063d041d59411610071578063d041d594146104a7578063d21220a7146104ca578063f2db11af146104f1578063f851a4401461054657600080fd5b8063c72a8c9514610465578063c812be311461046e578063ca4b208b14610481578063ce0e22b71461049457600080fd5b8063b8af3d3e116100de578063b8af3d3e14610382578063b9d8ce8914610395578063bd3bc19b1461039e578063c6b61e4c146103b157600080fd5b8063664c374114610331578063768d79f314610348578063a8aa1b311461035b57600080fd5b80632e1a7d4d116101715780634dd18bf51161014b5780634dd18bf5146102d157806353e083a8146102e457806356b7d7511461030b578063607bebe31461031e57600080fd5b80632e1a7d4d1461028b578063361ce2451461029e57806346f10881146102b157600080fd5b80631aef5e0d116101ad5780631aef5e0d146101f95780631cea75b61461023d57806326561b9214610250578063267822471461027857600080fd5b806304ca99d2146101d45780630e18b681146101e95780631a1ce2fc146101f1575b600080fd5b6101e76101e2366004612571565b610559565b005b6101e761059a565b6101e76106a3565b6102207f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6101e761024b3660046125cf565b610748565b61026361025e366004612637565b610947565b60408051928352602083019190915201610234565b600154610220906001600160a01b031681565b6101e7610299366004612571565b6109ba565b6101e76102ac366004612663565b610a00565b6102c46102bf36600461269b565b610a31565b60405161023491906126f0565b6101e76102df366004612734565b610c23565b6102207f000000000000000000000000000000000000000000000000000000000000000081565b6101e7610319366004612751565b610c85565b6101e761032c366004612773565b610cb5565b61033a60045481565b604051908152602001610234565b6101e761035636600461279f565b610cdc565b6102207f000000000000000000000000000000000000000000000000000000000000000081565b6101e7610390366004612571565b610e7f565b61033a60065481565b6101e76103ac3660046127f8565b610fa6565b6104186103bf366004612571565b6008602052600090815260409020805460018201546002830154600384015460048501546005860154600690960154949593949293919290919061ffff8082169162010000810490911690640100000000900460ff1689565b60408051998a5260208a0198909852968801959095526060870193909352608086019190915260a085015261ffff90811660c08501521660e0830152151561010082015261012001610234565b61033a60055481565b6101e761047c36600461285b565b6112a2565b600254610220906001600160a01b031681565b6101e76104a236600461279f565b6112d5565b6104ba6104b5366004612898565b611355565b6040519015158152602001610234565b6102207f000000000000000000000000000000000000000000000000000000000000000081565b61052b6104ff366004612902565b600760209081526000928352604080842090915290825290208054600182015460029092015490919083565b60408051938452602084019290925290820152606001610234565b600054610220906001600160a01b031681565b6105616113ac565b8062093a808110806105765750630784ce0081115b15610594576040516337bf561360e11b815260040160405180910390fd5b50600555565b6001546001600160a01b031633146105ed5760405162461bcd60e51b815260206004820152601160248201527027b7363c903832b73234b733a0b236b4b760791b60448201526064015b60405180910390fd5b60008054600180546001600160a01b038082166001600160a01b031980861682179096559490911690915560408051919092168082526020820184905292917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc910160405180910390a1600154604080516001600160a01b03808516825290921660208301527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a991015b60405180910390a15050565b6106ab6113ac565b6006546000036106ce5760405163162908e360e11b815260040160405180910390fd5b600680546000918290559054610711906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169116836113ff565b506040518181527f6282ca7732d1b80bfd787b44224abfc15a64c17fbef2bfc95c5fc06b30a06bee9060200160405180910390a150565b6000848152600860205260409020600381015442101561077b57604051636f312cbd60e01b815260040160405180910390fd5b80600401544211156107a057604051630407b05b60e31b815260040160405180910390fd5b8315806107be5750600181015460028201546107bc9086612948565b115b156107dc5760405163162908e360e11b815260040160405180910390fd5b600085815260076020908152604080832033845282529182902082516060810184528154808252600183015493820193909352600290910154928101929092521561083a5760405163ef89654560e01b815260040160405180910390fd5b61087d3383600001548787878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061160592505050565b61089a57604051635d2f8a0560e01b815260040160405180910390fd5b848260020160008282546108ae9190612948565b9091555050604080516060808201835287825260006020808401828152428587018181528d85526007845287852033808752908552948890209651875591516001870155905160029095019490945584518b8152908101919091529283018890528201527fc69c7dfb3e15d339bfed989be99d97589fc7bb295b3ab2db82829106001b9e2d9060800160405180910390a1505050505050565b60008181526007602090815260408083206001600160a01b0386168452825280832081516060810183528154808252600183015494820185905260029092015492810192909252839290036109a257600092508291506109b2565b6109ac818561165f565b90935091505b509250929050565b60006109c5826117cf565b90506109fb6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836113ff565b505050565b610a0861195e565b60026003556000610a1984336119b0565b9050610a26838284611a6b565b505060016003555050565b6060818067ffffffffffffffff811115610a4d57610a4d61295b565b604051908082528060200260200182016040528015610a76578160200160208202803683370190505b50915060005b81811015610c1a57600060076000878785818110610a9c57610a9c612971565b6020908102929092013583525081810192909252604090810160009081206001600160a01b038b16825283528190208151606081018352815480825260018301549482018590526002909201549281019290925290925003610b1e576000848381518110610b0c57610b0c612971565b60200260200101818152505050610c08565b600060086000888886818110610b3657610b36612971565b602090810292909201358352508181019290925260409081016000908120825161012081018452815481526001820154948101949094526002810154928401929092526003820154606084015260048201546080840152600582015460a084015260069091015461ffff80821660c08501526201000082041660e0840152640100000000900460ff161515610100830152909150610bd48383611bf2565b9050826020015181610be69190612987565b868581518110610bf857610bf8612971565b6020026020010181815250505050505b80610c128161299a565b915050610a7c565b50509392505050565b610c2b6113ac565b600180546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101610697565b610c8d61195e565b60026003556000610c9e83336119b0565b9050610cab338284611a6b565b5050600160035550565b610cbd61195e565b60026003556000610cce84336119b0565b9050610a2633828585611c55565b610ce46113ac565b6000805b82811015610e1d57600060086000868685818110610d0857610d08612971565b90506020020135815260200190815260200160002090508060060160049054906101000a900460ff1615610d4f576040516336b5f2f760e11b815260040160405180910390fd5b80600401544211610d735760405163d0404f8560e01b815260040160405180910390fd5b600081600201548260010154610d899190612987565b9050610d958185612948565b60068301805464ff00000000191664010000000017905593507fadb56f2e8c8dd63466fb638690ea115eeb4f568e6e732d67200d1646b15ece75868685818110610de157610de1612971565b9050602002013582604051610e00929190918252602082015260400190565b60405180910390a150508080610e159061299a565b915050610ce8565b5080600003610e3f5760405163162908e360e11b815260040160405180910390fd5b600054610e79906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169116836113ff565b50505050565b6000818152600760209081526040808320338452909152902080541580610eaa575060018101548154145b15610ec85760405163162908e360e11b815260040160405180910390fd5b600080610efe8360405180606001604052908160008201548152602001600182015481526020016002820154815250508561165f565b84546001860155600680549294509092508291600090610f1f908490612948565b909155505060408051858152336020820152908101839052606081018290527f1c84cc0f96161bdafea718a9094dd21c21d1fb2f9ca2ebb9bd4e39918efbaace9060800160405180910390a1610f9f6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633846113ff565b5050505050565b6000546001600160a01b0316331480610fc957506002546001600160a01b031633145b6110095760405162461bcd60e51b815260206004820152601160248201527027b7363c9030b236b4b71037b9103232bb60791b60448201526064016105e4565b8262093a8081108061101e5750630784ce0081115b1561103c576040516337bf561360e11b815260040160405180910390fd5b858511158061104b5750428511155b15611069576040516337bf561360e11b815260040160405180910390fd5b861580611085575061271061107e83856129b3565b61ffff1610155b156110a35760405163162908e360e11b815260040160405180910390fd5b60006110da6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633308b611d37565b90508781146110fb576040516276f4ff60e41b815260040160405180910390fd5b600060046000815461110c9061299a565b91905081905590506040518061012001604052808b81526020018a8152602001600081526020018981526020018881526020018781526020018661ffff1681526020018561ffff1681526020016000151581525060086000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c08201518160060160006101000a81548161ffff021916908361ffff16021790555060e08201518160060160026101000a81548161ffff021916908361ffff1602179055506101008201518160060160046101000a81548160ff0219169083151502179055509050507f9a5ab6171e45c59f905bba9a5e5d913c4457dfb38e5b695f717aa33b6b6c1362818b8b8b8b8b8b8b60405161128e989796959493929190978852602088019690965260408701949094526060860192909252608085015260a084015261ffff90811660c08401521660e08201526101000190565b60405180910390a150505050505050505050565b6112aa61195e565b600260035560006112bb85336119b0565b90506112c984828585611c55565b50506001600355505050565b6000805b82811015611320576113028484838181106112f6576112f6612971565b905060200201356117cf565b61130c9083612948565b9150806113188161299a565b9150506112d9565b50610e796001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836113ff565b600084815260086020908152604080832054815185840281810185019093528581526113a2938a938992918991899182919085019084908082843760009201919091525061160592505050565b9695505050505050565b6000546001600160a01b031633146113fd5760405162461bcd60e51b815260206004820152601460248201527331b0b63632b91036bab9ba1031329030b236b4b760611b60448201526064016105e4565b565b600081156115fe576040516370a0823160e01b81526001600160a01b03848116600483015260009182918716906370a0823190602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906129ce565b604080516001600160a01b038881166024830152604480830189905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151929350908816916114d091906129e7565b6000604051808303816000865af19150503d806000811461150d576040519150601f19603f3d011682016040523d82523d6000602084013e611512565b606091505b5050809250508161154a5760405162461bcd60e51b81526020600482015260026024820152612a2360f11b60448201526064016105e4565b6040516370a0823160e01b81526001600160a01b038681166004830152600091908816906370a0823190602401602060405180830381865afa158015611594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b891906129ce565b90508181116115ee5760405162461bcd60e51b81526020600482015260026024820152612a2360f11b60448201526064016105e4565b6115f88282612987565b93505050505b9392505050565b6040516bffffffffffffffffffffffff19606086901b166020820152603481018390526000908190605401604051602081830303815290604052805190602001209050611653838683611f46565b9150505b949350505050565b6000818152600860209081526040808320815161012081018352815481526001820154938101939093526002810154918301919091526003810154606083015260048101546080830152600581015460a08301526006015461ffff80821660c08401526201000082041660e0830152640100000000900460ff1615156101008201528190816116ee8683611bf2565b90508560200151816117009190612987565b935060008260a0015187604001516117189190612948565b905060008360c0015161ffff168460a001518560e0015161ffff16428561173f9190612987565b6117499190612a16565b6117539190612a2d565b61175d9190612948565b905060008389600001516117719190612987565b90506127106117808383612a16565b61178a9190612a2d565b95508086106117ac5760405163458eae5b60e01b815260040160405180910390fd5b6117b68682612987565b6117c09088612948565b965050505050505b9250929050565b60008181526007602090815260408083203384529091528120805415806117fa575060018101548154145b156118185760405163162908e360e11b815260040160405180910390fd5b6000838152600860209081526040808320815161012081018352815481526001808301548286015260028084015483860152600384015460608085019190915260048501546080850152600585015460a085015260069094015461ffff80821660c08601526201000082041660e0850152640100000000900460ff16151561010084015290870154845193840185528754845294830185905286015492820192909252909291906118c99084611bf2565b6118d39190612987565b9050806000036118f65760405163162908e360e11b815260040160405180910390fd5b8083600101600082825461190a9190612948565b909155505060408051868152336020820152908101829052600060608201527f1c84cc0f96161bdafea718a9094dd21c21d1fb2f9ca2ebb9bd4e39918efbaace9060800160405180910390a1949350505050565b6002600354036113fd5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105e4565b60008281526007602090815260408083206001600160a01b038516845290915281206001810154815483916119e491612987565b825490915015806119f3575080155b15611a115760405163162908e360e11b815260040160405180910390fd5b81546001830155604080518681526001600160a01b03861660208201529081018290527f0235b6790a877095b8878d0a0e0af7c5442875c0ac9f901c07584ff6f71d9d6d9060600160405180910390a19150505b92915050565b60405163cbf9fe5f60e01b81526001600160a01b0384811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063cbf9fe5f906024016040805180830381865afa158015611ad5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af99190612a4f565b915050611b0581611f5c565b6000611b118484611fa3565b9050611b676001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000083612168565b5060405163743241bb60e11b81526001600160a01b038681166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063e8648376906044015b600060405180830381600087803b158015611bd357600080fd5b505af1158015611be7573d6000803e3d6000fd5b505050505050505050565b6000808260a001518460400151611c099190612948565b905080421115611c1c5750508151611a65565b60a083015184516040860151611c329042612987565b611c3c9190612a16565b611c469190612a2d565b915050611a65565b5092915050565b62093a80611c638183612a2d565b611c6d9190612a16565b9050611c7881611f5c565b6000611c848484611fa3565b9050611cda6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000083612168565b50604051633e173b2960e01b81526001600160a01b03868116600483015260248201839052604482018490527f00000000000000000000000000000000000000000000000000000000000000001690633e173b2990606401611bb9565b60008115611657576040516370a0823160e01b81526001600160a01b03848116600483015260009182918816906370a0823190602401602060405180830381865afa158015611d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dae91906129ce565b604080516001600160a01b0389811660248301528881166044830152606480830189905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b179052915192935090891691611e1091906129e7565b6000604051808303816000865af19150503d8060008114611e4d576040519150601f19603f3d011682016040523d82523d6000602084013e611e52565b606091505b50508092505081611e8b5760405162461bcd60e51b81526020600482015260036024820152622a232360e91b60448201526064016105e4565b6040516370a0823160e01b81526001600160a01b038681166004830152600091908916906370a0823190602401602060405180830381865afa158015611ed5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef991906129ce565b9050818111611f305760405162461bcd60e51b81526020600482015260036024820152622a232360e91b60448201526064016105e4565b611f3a8282612987565b98975050505050505050565b600082611f538584612400565b14949350505050565b600554611f699042612948565b811080611f825750611f7f630784ce0042612948565b81115b15611fa0576040516337bf561360e11b815260040160405180910390fd5b50565b6000806000611ff27f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061244d565b90925090506000826120048388612a16565b61200e9190612a2d565b9050848111156120335760405162d3c55f60e61b8152600481018290526024016105e4565b6120886001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016337f000000000000000000000000000000000000000000000000000000000000000084611d37565b506120dd6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000886113ff565b506040516335313c2160e11b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636a627842906024016020604051808303816000875af1158015612144573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a291906129ce565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091829186169063dd62ed3e90604401602060405180830381865afa1580156121b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121dd91906129ce565b156122b657604080516001600160a01b038681166024830152600060448084019190915283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291519187169161223c91906129e7565b6000604051808303816000865af19150503d8060008114612279576040519150601f19603f3d011682016040523d82523d6000602084013e61227e565b606091505b505080915050806122b65760405162461bcd60e51b815260206004820152600260248201526120a360f11b60448201526064016105e4565b604080516001600160a01b038681166024830152604480830187905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291519187169161230d91906129e7565b6000604051808303816000865af19150503d806000811461234a576040519150601f19603f3d011682016040523d82523d6000602084013e61234f565b606091505b505080915050806123875760405162461bcd60e51b815260206004820152600260248201526120a360f11b60448201526064016105e4565b604051636eb1769f60e11b81523060048201526001600160a01b03858116602483015286169063dd62ed3e90604401602060405180830381865afa1580156123d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f791906129ce565b95945050505050565b600081815b8451811015612445576124318286838151811061242457612424612971565b6020026020010151612545565b91508061243d8161299a565b915050612405565b509392505050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156124b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d59190612a8a565b506001600160701b031691506001600160701b031691506000856001600160a01b0316876001600160a01b03161061250e578587612511565b86865b509050806001600160a01b0316876001600160a01b031614612534578183612537565b82825b909890975095505050505050565b60008183106125615760008281526020849052604090206115fe565b5060009182526020526040902090565b60006020828403121561258357600080fd5b5035919050565b60008083601f84011261259c57600080fd5b50813567ffffffffffffffff8111156125b457600080fd5b6020830191508360208260051b85010111156117c857600080fd5b600080600080606085870312156125e557600080fd5b8435935060208501359250604085013567ffffffffffffffff81111561260a57600080fd5b6126168782880161258a565b95989497509550505050565b6001600160a01b0381168114611fa057600080fd5b6000806040838503121561264a57600080fd5b823561265581612622565b946020939093013593505050565b60008060006060848603121561267857600080fd5b83359250602084013561268a81612622565b929592945050506040919091013590565b6000806000604084860312156126b057600080fd5b83356126bb81612622565b9250602084013567ffffffffffffffff8111156126d757600080fd5b6126e38682870161258a565b9497909650939450505050565b6020808252825182820181905260009190848201906040850190845b818110156127285783518352928401929184019160010161270c565b50909695505050505050565b60006020828403121561274657600080fd5b81356115fe81612622565b6000806040838503121561276457600080fd5b50508035926020909101359150565b60008060006060848603121561278857600080fd5b505081359360208301359350604090920135919050565b600080602083850312156127b257600080fd5b823567ffffffffffffffff8111156127c957600080fd5b6127d58582860161258a565b90969095509350505050565b803561ffff811681146127f357600080fd5b919050565b600080600080600080600060e0888a03121561281357600080fd5b873596506020880135955060408801359450606088013593506080880135925061283f60a089016127e1565b915061284d60c089016127e1565b905092959891949750929550565b6000806000806080858703121561287157600080fd5b84359350602085013561288381612622565b93969395505050506040820135916060013590565b6000806000806000608086880312156128b057600080fd5b85356128bb81612622565b94506020860135935060408601359250606086013567ffffffffffffffff8111156128e557600080fd5b6128f18882890161258a565b969995985093965092949392505050565b6000806040838503121561291557600080fd5b82359150602083013561292781612622565b809150509250929050565b634e487b7160e01b600052601160045260246000fd5b80820180821115611a6557611a65612932565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b81810381811115611a6557611a65612932565b6000600182016129ac576129ac612932565b5060010190565b61ffff818116838216019080821115611c4e57611c4e612932565b6000602082840312156129e057600080fd5b5051919050565b6000825160005b81811015612a0857602081860181015185830152016129ee565b506000920191825250919050565b8082028115828204841417611a6557611a65612932565b600082612a4a57634e487b7160e01b600052601260045260246000fd5b500490565b60008060408385031215612a6257600080fd5b505080516020909101519092909150565b80516001600160701b03811681146127f357600080fd5b600080600060608486031215612a9f57600080fd5b612aa884612a73565b9250612ab660208501612a73565b9150604084015163ffffffff81168114612acf57600080fd5b80915050925092509256fea2646970667358221220e8750343cb1fe1e65198b0a3e5bac082b2a8897d600a33e5ce0f7e8108ab210364736f6c634300081100330000000000000000000000007be5dd337cc6ce3e474f64e2a92a566445290864000000000000000000000000fdb2c36b73e18871d9208cc508c911a1bffcfb8e000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000001c59529ba394427d9a18a3ef6b8ca38906b8e2db000000000000000000000000000000000000000000000000000000000024ea00

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063664c374111610104578063c72a8c95116100a2578063d041d59411610071578063d041d594146104a7578063d21220a7146104ca578063f2db11af146104f1578063f851a4401461054657600080fd5b8063c72a8c9514610465578063c812be311461046e578063ca4b208b14610481578063ce0e22b71461049457600080fd5b8063b8af3d3e116100de578063b8af3d3e14610382578063b9d8ce8914610395578063bd3bc19b1461039e578063c6b61e4c146103b157600080fd5b8063664c374114610331578063768d79f314610348578063a8aa1b311461035b57600080fd5b80632e1a7d4d116101715780634dd18bf51161014b5780634dd18bf5146102d157806353e083a8146102e457806356b7d7511461030b578063607bebe31461031e57600080fd5b80632e1a7d4d1461028b578063361ce2451461029e57806346f10881146102b157600080fd5b80631aef5e0d116101ad5780631aef5e0d146101f95780631cea75b61461023d57806326561b9214610250578063267822471461027857600080fd5b806304ca99d2146101d45780630e18b681146101e95780631a1ce2fc146101f1575b600080fd5b6101e76101e2366004612571565b610559565b005b6101e761059a565b6101e76106a3565b6102207f0000000000000000000000001c59529ba394427d9a18a3ef6b8ca38906b8e2db81565b6040516001600160a01b0390911681526020015b60405180910390f35b6101e761024b3660046125cf565b610748565b61026361025e366004612637565b610947565b60408051928352602083019190915201610234565b600154610220906001600160a01b031681565b6101e7610299366004612571565b6109ba565b6101e76102ac366004612663565b610a00565b6102c46102bf36600461269b565b610a31565b60405161023491906126f0565b6101e76102df366004612734565b610c23565b6102207f0000000000000000000000007be5dd337cc6ce3e474f64e2a92a56644529086481565b6101e7610319366004612751565b610c85565b6101e761032c366004612773565b610cb5565b61033a60045481565b604051908152602001610234565b6101e761035636600461279f565b610cdc565b6102207f000000000000000000000000fdb2c36b73e18871d9208cc508c911a1bffcfb8e81565b6101e7610390366004612571565b610e7f565b61033a60065481565b6101e76103ac3660046127f8565b610fa6565b6104186103bf366004612571565b6008602052600090815260409020805460018201546002830154600384015460048501546005860154600690960154949593949293919290919061ffff8082169162010000810490911690640100000000900460ff1689565b60408051998a5260208a0198909852968801959095526060870193909352608086019190915260a085015261ffff90811660c08501521660e0830152151561010082015261012001610234565b61033a60055481565b6101e761047c36600461285b565b6112a2565b600254610220906001600160a01b031681565b6101e76104a236600461279f565b6112d5565b6104ba6104b5366004612898565b611355565b6040519015158152602001610234565b6102207f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e583181565b61052b6104ff366004612902565b600760209081526000928352604080842090915290825290208054600182015460029092015490919083565b60408051938452602084019290925290820152606001610234565b600054610220906001600160a01b031681565b6105616113ac565b8062093a808110806105765750630784ce0081115b15610594576040516337bf561360e11b815260040160405180910390fd5b50600555565b6001546001600160a01b031633146105ed5760405162461bcd60e51b815260206004820152601160248201527027b7363c903832b73234b733a0b236b4b760791b60448201526064015b60405180910390fd5b60008054600180546001600160a01b038082166001600160a01b031980861682179096559490911690915560408051919092168082526020820184905292917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc910160405180910390a1600154604080516001600160a01b03808516825290921660208301527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a991015b60405180910390a15050565b6106ab6113ac565b6006546000036106ce5760405163162908e360e11b815260040160405180910390fd5b600680546000918290559054610711906001600160a01b037f0000000000000000000000007be5dd337cc6ce3e474f64e2a92a56644529086481169116836113ff565b506040518181527f6282ca7732d1b80bfd787b44224abfc15a64c17fbef2bfc95c5fc06b30a06bee9060200160405180910390a150565b6000848152600860205260409020600381015442101561077b57604051636f312cbd60e01b815260040160405180910390fd5b80600401544211156107a057604051630407b05b60e31b815260040160405180910390fd5b8315806107be5750600181015460028201546107bc9086612948565b115b156107dc5760405163162908e360e11b815260040160405180910390fd5b600085815260076020908152604080832033845282529182902082516060810184528154808252600183015493820193909352600290910154928101929092521561083a5760405163ef89654560e01b815260040160405180910390fd5b61087d3383600001548787878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061160592505050565b61089a57604051635d2f8a0560e01b815260040160405180910390fd5b848260020160008282546108ae9190612948565b9091555050604080516060808201835287825260006020808401828152428587018181528d85526007845287852033808752908552948890209651875591516001870155905160029095019490945584518b8152908101919091529283018890528201527fc69c7dfb3e15d339bfed989be99d97589fc7bb295b3ab2db82829106001b9e2d9060800160405180910390a1505050505050565b60008181526007602090815260408083206001600160a01b0386168452825280832081516060810183528154808252600183015494820185905260029092015492810192909252839290036109a257600092508291506109b2565b6109ac818561165f565b90935091505b509250929050565b60006109c5826117cf565b90506109fb6001600160a01b037f0000000000000000000000007be5dd337cc6ce3e474f64e2a92a5664452908641633836113ff565b505050565b610a0861195e565b60026003556000610a1984336119b0565b9050610a26838284611a6b565b505060016003555050565b6060818067ffffffffffffffff811115610a4d57610a4d61295b565b604051908082528060200260200182016040528015610a76578160200160208202803683370190505b50915060005b81811015610c1a57600060076000878785818110610a9c57610a9c612971565b6020908102929092013583525081810192909252604090810160009081206001600160a01b038b16825283528190208151606081018352815480825260018301549482018590526002909201549281019290925290925003610b1e576000848381518110610b0c57610b0c612971565b60200260200101818152505050610c08565b600060086000888886818110610b3657610b36612971565b602090810292909201358352508181019290925260409081016000908120825161012081018452815481526001820154948101949094526002810154928401929092526003820154606084015260048201546080840152600582015460a084015260069091015461ffff80821660c08501526201000082041660e0840152640100000000900460ff161515610100830152909150610bd48383611bf2565b9050826020015181610be69190612987565b868581518110610bf857610bf8612971565b6020026020010181815250505050505b80610c128161299a565b915050610a7c565b50509392505050565b610c2b6113ac565b600180546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101610697565b610c8d61195e565b60026003556000610c9e83336119b0565b9050610cab338284611a6b565b5050600160035550565b610cbd61195e565b60026003556000610cce84336119b0565b9050610a2633828585611c55565b610ce46113ac565b6000805b82811015610e1d57600060086000868685818110610d0857610d08612971565b90506020020135815260200190815260200160002090508060060160049054906101000a900460ff1615610d4f576040516336b5f2f760e11b815260040160405180910390fd5b80600401544211610d735760405163d0404f8560e01b815260040160405180910390fd5b600081600201548260010154610d899190612987565b9050610d958185612948565b60068301805464ff00000000191664010000000017905593507fadb56f2e8c8dd63466fb638690ea115eeb4f568e6e732d67200d1646b15ece75868685818110610de157610de1612971565b9050602002013582604051610e00929190918252602082015260400190565b60405180910390a150508080610e159061299a565b915050610ce8565b5080600003610e3f5760405163162908e360e11b815260040160405180910390fd5b600054610e79906001600160a01b037f0000000000000000000000007be5dd337cc6ce3e474f64e2a92a56644529086481169116836113ff565b50505050565b6000818152600760209081526040808320338452909152902080541580610eaa575060018101548154145b15610ec85760405163162908e360e11b815260040160405180910390fd5b600080610efe8360405180606001604052908160008201548152602001600182015481526020016002820154815250508561165f565b84546001860155600680549294509092508291600090610f1f908490612948565b909155505060408051858152336020820152908101839052606081018290527f1c84cc0f96161bdafea718a9094dd21c21d1fb2f9ca2ebb9bd4e39918efbaace9060800160405180910390a1610f9f6001600160a01b037f0000000000000000000000007be5dd337cc6ce3e474f64e2a92a5664452908641633846113ff565b5050505050565b6000546001600160a01b0316331480610fc957506002546001600160a01b031633145b6110095760405162461bcd60e51b815260206004820152601160248201527027b7363c9030b236b4b71037b9103232bb60791b60448201526064016105e4565b8262093a8081108061101e5750630784ce0081115b1561103c576040516337bf561360e11b815260040160405180910390fd5b858511158061104b5750428511155b15611069576040516337bf561360e11b815260040160405180910390fd5b861580611085575061271061107e83856129b3565b61ffff1610155b156110a35760405163162908e360e11b815260040160405180910390fd5b60006110da6001600160a01b037f0000000000000000000000007be5dd337cc6ce3e474f64e2a92a5664452908641633308b611d37565b90508781146110fb576040516276f4ff60e41b815260040160405180910390fd5b600060046000815461110c9061299a565b91905081905590506040518061012001604052808b81526020018a8152602001600081526020018981526020018881526020018781526020018661ffff1681526020018561ffff1681526020016000151581525060086000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c08201518160060160006101000a81548161ffff021916908361ffff16021790555060e08201518160060160026101000a81548161ffff021916908361ffff1602179055506101008201518160060160046101000a81548160ff0219169083151502179055509050507f9a5ab6171e45c59f905bba9a5e5d913c4457dfb38e5b695f717aa33b6b6c1362818b8b8b8b8b8b8b60405161128e989796959493929190978852602088019690965260408701949094526060860192909252608085015260a084015261ffff90811660c08401521660e08201526101000190565b60405180910390a150505050505050505050565b6112aa61195e565b600260035560006112bb85336119b0565b90506112c984828585611c55565b50506001600355505050565b6000805b82811015611320576113028484838181106112f6576112f6612971565b905060200201356117cf565b61130c9083612948565b9150806113188161299a565b9150506112d9565b50610e796001600160a01b037f0000000000000000000000007be5dd337cc6ce3e474f64e2a92a5664452908641633836113ff565b600084815260086020908152604080832054815185840281810185019093528581526113a2938a938992918991899182919085019084908082843760009201919091525061160592505050565b9695505050505050565b6000546001600160a01b031633146113fd5760405162461bcd60e51b815260206004820152601460248201527331b0b63632b91036bab9ba1031329030b236b4b760611b60448201526064016105e4565b565b600081156115fe576040516370a0823160e01b81526001600160a01b03848116600483015260009182918716906370a0823190602401602060405180830381865afa158015611452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147691906129ce565b604080516001600160a01b038881166024830152604480830189905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151929350908816916114d091906129e7565b6000604051808303816000865af19150503d806000811461150d576040519150601f19603f3d011682016040523d82523d6000602084013e611512565b606091505b5050809250508161154a5760405162461bcd60e51b81526020600482015260026024820152612a2360f11b60448201526064016105e4565b6040516370a0823160e01b81526001600160a01b038681166004830152600091908816906370a0823190602401602060405180830381865afa158015611594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b891906129ce565b90508181116115ee5760405162461bcd60e51b81526020600482015260026024820152612a2360f11b60448201526064016105e4565b6115f88282612987565b93505050505b9392505050565b6040516bffffffffffffffffffffffff19606086901b166020820152603481018390526000908190605401604051602081830303815290604052805190602001209050611653838683611f46565b9150505b949350505050565b6000818152600860209081526040808320815161012081018352815481526001820154938101939093526002810154918301919091526003810154606083015260048101546080830152600581015460a08301526006015461ffff80821660c08401526201000082041660e0830152640100000000900460ff1615156101008201528190816116ee8683611bf2565b90508560200151816117009190612987565b935060008260a0015187604001516117189190612948565b905060008360c0015161ffff168460a001518560e0015161ffff16428561173f9190612987565b6117499190612a16565b6117539190612a2d565b61175d9190612948565b905060008389600001516117719190612987565b90506127106117808383612a16565b61178a9190612a2d565b95508086106117ac5760405163458eae5b60e01b815260040160405180910390fd5b6117b68682612987565b6117c09088612948565b965050505050505b9250929050565b60008181526007602090815260408083203384529091528120805415806117fa575060018101548154145b156118185760405163162908e360e11b815260040160405180910390fd5b6000838152600860209081526040808320815161012081018352815481526001808301548286015260028084015483860152600384015460608085019190915260048501546080850152600585015460a085015260069094015461ffff80821660c08601526201000082041660e0850152640100000000900460ff16151561010084015290870154845193840185528754845294830185905286015492820192909252909291906118c99084611bf2565b6118d39190612987565b9050806000036118f65760405163162908e360e11b815260040160405180910390fd5b8083600101600082825461190a9190612948565b909155505060408051868152336020820152908101829052600060608201527f1c84cc0f96161bdafea718a9094dd21c21d1fb2f9ca2ebb9bd4e39918efbaace9060800160405180910390a1949350505050565b6002600354036113fd5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105e4565b60008281526007602090815260408083206001600160a01b038516845290915281206001810154815483916119e491612987565b825490915015806119f3575080155b15611a115760405163162908e360e11b815260040160405180910390fd5b81546001830155604080518681526001600160a01b03861660208201529081018290527f0235b6790a877095b8878d0a0e0af7c5442875c0ac9f901c07584ff6f71d9d6d9060600160405180910390a19150505b92915050565b60405163cbf9fe5f60e01b81526001600160a01b0384811660048301526000917f0000000000000000000000001c59529ba394427d9a18a3ef6b8ca38906b8e2db9091169063cbf9fe5f906024016040805180830381865afa158015611ad5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af99190612a4f565b915050611b0581611f5c565b6000611b118484611fa3565b9050611b676001600160a01b037f000000000000000000000000fdb2c36b73e18871d9208cc508c911a1bffcfb8e167f0000000000000000000000001c59529ba394427d9a18a3ef6b8ca38906b8e2db83612168565b5060405163743241bb60e11b81526001600160a01b038681166004830152602482018390527f0000000000000000000000001c59529ba394427d9a18a3ef6b8ca38906b8e2db169063e8648376906044015b600060405180830381600087803b158015611bd357600080fd5b505af1158015611be7573d6000803e3d6000fd5b505050505050505050565b6000808260a001518460400151611c099190612948565b905080421115611c1c5750508151611a65565b60a083015184516040860151611c329042612987565b611c3c9190612a16565b611c469190612a2d565b915050611a65565b5092915050565b62093a80611c638183612a2d565b611c6d9190612a16565b9050611c7881611f5c565b6000611c848484611fa3565b9050611cda6001600160a01b037f000000000000000000000000fdb2c36b73e18871d9208cc508c911a1bffcfb8e167f0000000000000000000000001c59529ba394427d9a18a3ef6b8ca38906b8e2db83612168565b50604051633e173b2960e01b81526001600160a01b03868116600483015260248201839052604482018490527f0000000000000000000000001c59529ba394427d9a18a3ef6b8ca38906b8e2db1690633e173b2990606401611bb9565b60008115611657576040516370a0823160e01b81526001600160a01b03848116600483015260009182918816906370a0823190602401602060405180830381865afa158015611d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dae91906129ce565b604080516001600160a01b0389811660248301528881166044830152606480830189905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b179052915192935090891691611e1091906129e7565b6000604051808303816000865af19150503d8060008114611e4d576040519150601f19603f3d011682016040523d82523d6000602084013e611e52565b606091505b50508092505081611e8b5760405162461bcd60e51b81526020600482015260036024820152622a232360e91b60448201526064016105e4565b6040516370a0823160e01b81526001600160a01b038681166004830152600091908916906370a0823190602401602060405180830381865afa158015611ed5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef991906129ce565b9050818111611f305760405162461bcd60e51b81526020600482015260036024820152622a232360e91b60448201526064016105e4565b611f3a8282612987565b98975050505050505050565b600082611f538584612400565b14949350505050565b600554611f699042612948565b811080611f825750611f7f630784ce0042612948565b81115b15611fa0576040516337bf561360e11b815260040160405180910390fd5b50565b6000806000611ff27f0000000000000000000000007be5dd337cc6ce3e474f64e2a92a5664452908647f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e583161244d565b90925090506000826120048388612a16565b61200e9190612a2d565b9050848111156120335760405162d3c55f60e61b8152600481018290526024016105e4565b6120886001600160a01b037f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e583116337f000000000000000000000000fdb2c36b73e18871d9208cc508c911a1bffcfb8e84611d37565b506120dd6001600160a01b037f0000000000000000000000007be5dd337cc6ce3e474f64e2a92a566445290864167f000000000000000000000000fdb2c36b73e18871d9208cc508c911a1bffcfb8e886113ff565b506040516335313c2160e11b81523060048201527f000000000000000000000000fdb2c36b73e18871d9208cc508c911a1bffcfb8e6001600160a01b031690636a627842906024016020604051808303816000875af1158015612144573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a291906129ce565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091829186169063dd62ed3e90604401602060405180830381865afa1580156121b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121dd91906129ce565b156122b657604080516001600160a01b038681166024830152600060448084019190915283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291519187169161223c91906129e7565b6000604051808303816000865af19150503d8060008114612279576040519150601f19603f3d011682016040523d82523d6000602084013e61227e565b606091505b505080915050806122b65760405162461bcd60e51b815260206004820152600260248201526120a360f11b60448201526064016105e4565b604080516001600160a01b038681166024830152604480830187905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291519187169161230d91906129e7565b6000604051808303816000865af19150503d806000811461234a576040519150601f19603f3d011682016040523d82523d6000602084013e61234f565b606091505b505080915050806123875760405162461bcd60e51b815260206004820152600260248201526120a360f11b60448201526064016105e4565b604051636eb1769f60e11b81523060048201526001600160a01b03858116602483015286169063dd62ed3e90604401602060405180830381865afa1580156123d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f791906129ce565b95945050505050565b600081815b8451811015612445576124318286838151811061242457612424612971565b6020026020010151612545565b91508061243d8161299a565b915050612405565b509392505050565b6000806000807f000000000000000000000000fdb2c36b73e18871d9208cc508c911a1bffcfb8e6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156124b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d59190612a8a565b506001600160701b031691506001600160701b031691506000856001600160a01b0316876001600160a01b03161061250e578587612511565b86865b509050806001600160a01b0316876001600160a01b031614612534578183612537565b82825b909890975095505050505050565b60008183106125615760008281526020849052604090206115fe565b5060009182526020526040902090565b60006020828403121561258357600080fd5b5035919050565b60008083601f84011261259c57600080fd5b50813567ffffffffffffffff8111156125b457600080fd5b6020830191508360208260051b85010111156117c857600080fd5b600080600080606085870312156125e557600080fd5b8435935060208501359250604085013567ffffffffffffffff81111561260a57600080fd5b6126168782880161258a565b95989497509550505050565b6001600160a01b0381168114611fa057600080fd5b6000806040838503121561264a57600080fd5b823561265581612622565b946020939093013593505050565b60008060006060848603121561267857600080fd5b83359250602084013561268a81612622565b929592945050506040919091013590565b6000806000604084860312156126b057600080fd5b83356126bb81612622565b9250602084013567ffffffffffffffff8111156126d757600080fd5b6126e38682870161258a565b9497909650939450505050565b6020808252825182820181905260009190848201906040850190845b818110156127285783518352928401929184019160010161270c565b50909695505050505050565b60006020828403121561274657600080fd5b81356115fe81612622565b6000806040838503121561276457600080fd5b50508035926020909101359150565b60008060006060848603121561278857600080fd5b505081359360208301359350604090920135919050565b600080602083850312156127b257600080fd5b823567ffffffffffffffff8111156127c957600080fd5b6127d58582860161258a565b90969095509350505050565b803561ffff811681146127f357600080fd5b919050565b600080600080600080600060e0888a03121561281357600080fd5b873596506020880135955060408801359450606088013593506080880135925061283f60a089016127e1565b915061284d60c089016127e1565b905092959891949750929550565b6000806000806080858703121561287157600080fd5b84359350602085013561288381612622565b93969395505050506040820135916060013590565b6000806000806000608086880312156128b057600080fd5b85356128bb81612622565b94506020860135935060408601359250606086013567ffffffffffffffff8111156128e557600080fd5b6128f18882890161258a565b969995985093965092949392505050565b6000806040838503121561291557600080fd5b82359150602083013561292781612622565b809150509250929050565b634e487b7160e01b600052601160045260246000fd5b80820180821115611a6557611a65612932565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b81810381811115611a6557611a65612932565b6000600182016129ac576129ac612932565b5060010190565b61ffff818116838216019080821115611c4e57611c4e612932565b6000602082840312156129e057600080fd5b5051919050565b6000825160005b81811015612a0857602081860181015185830152016129ee565b506000920191825250919050565b8082028115828204841417611a6557611a65612932565b600082612a4a57634e487b7160e01b600052601260045260246000fd5b500490565b60008060408385031215612a6257600080fd5b505080516020909101519092909150565b80516001600160701b03811681146127f357600080fd5b600080600060608486031215612a9f57600080fd5b612aa884612a73565b9250612ab660208501612a73565b9150604084015163ffffffff81168114612acf57600080fd5b80915050925092509256fea2646970667358221220e8750343cb1fe1e65198b0a3e5bac082b2a8897d600a33e5ce0f7e8108ab210364736f6c63430008110033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000007be5dd337cc6ce3e474f64e2a92a566445290864000000000000000000000000fdb2c36b73e18871d9208cc508c911a1bffcfb8e000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000001c59529ba394427d9a18a3ef6b8ca38906b8e2db000000000000000000000000000000000000000000000000000000000024ea00

-----Decoded View---------------
Arg [0] : _oleToken (address): 0x7Be5Dd337CC6cE3e474F64E2A92A566445290864
Arg [1] : _pair (address): 0xFdB2C36b73e18871D9208cc508c911A1bFFCFB8e
Arg [2] : _token1 (address): 0xaf88d065e77c8cC2239327C5EDb3A432268e5831
Arg [3] : _xole (address): 0x1c59529ba394427D9a18A3eF6B8CA38906b8E2dB
Arg [4] : _minXOLELockDuration (uint256): 2419200

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000007be5dd337cc6ce3e474f64e2a92a566445290864
Arg [1] : 000000000000000000000000fdb2c36b73e18871d9208cc508c911a1bffcfb8e
Arg [2] : 000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831
Arg [3] : 0000000000000000000000001c59529ba394427d9a18a3ef6b8ca38906b8e2db
Arg [4] : 000000000000000000000000000000000000000000000000000000000024ea00


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
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.