ETH Price: $2,453.82 (-1.04%)
Gas: 8.37 Gwei

Contract

0x5bE1Aac0Ce9BD53B49179a37508C318eE146E508
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0x60806040117441332021-01-28 11:53:391375 days ago1611834819IN
 Create: StakePoolEpochRewardCreator
0 ETH0.1664637455.055

Latest 2 internal transactions

Advanced mode:
Parent Transaction Hash Block From To
117445462021-01-28 13:22:371374 days ago1611840157
0x5bE1Aac0...eE146E508
 Contract Creation0 ETH
117445372021-01-28 13:20:461374 days ago1611840046
0x5bE1Aac0...eE146E508
 Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
StakePoolEpochRewardCreator

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 999999 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-01-28
*/

// SPDX-License-Identifier: SEE LICENSE IN LICENSE

pragma abicoder v2;
pragma solidity >=0.7.6;

interface IStakePoolCreator {
    function version() external returns (uint256);

    function create() external returns (address);

    function initialize(
        address poolAddress,
        address pair,
        address rewardToken,
        address timelock,
        address stakePoolRewardFund,
        bytes calldata data
    ) external;
}

interface IValueLiquidRouter {
    struct Swap {
        address pool;
        address tokenIn;
        address tokenOut;
        uint256 swapAmount; // tokenInAmount / tokenOutAmount
        uint256 limitReturnAmount; // minAmountOut / maxAmountIn
        uint256 maxPrice;
        bool isBPool;
    }

    function factory() external view returns (address);

    function controller() external view returns (address);

    function formula() external view returns (address);

    function WETH() external view returns (address);

    function addLiquidity(
        address pair,
        address tokenA,
        address tokenB,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    )
        external
        returns (
            uint256 amountA,
            uint256 amountB,
            uint256 liquidity
        );

    function addLiquidityETH(
        address pair,
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    )
        external
        payable
        returns (
            uint256 amountToken,
            uint256 amountETH,
            uint256 liquidity
        );

    function swapExactTokensForTokens(
        address tokenIn,
        address tokenOut,
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline,
        uint8 flag
    ) external returns (uint256[] memory amounts);

    function swapTokensForExactTokens(
        address tokenIn,
        address tokenOut,
        uint256 amountOut,
        uint256 amountInMax,
        address[] calldata path,
        address to,
        uint256 deadline,
        uint8 flag
    ) external returns (uint256[] memory amounts);

    function swapExactETHForTokens(
        address tokenOut,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline,
        uint8 flag
    ) external payable returns (uint256[] memory amounts);

    function swapTokensForExactETH(
        address tokenIn,
        uint256 amountOut,
        uint256 amountInMax,
        address[] calldata path,
        address to,
        uint256 deadline,
        uint8 flag
    ) external returns (uint256[] memory amounts);

    function swapExactTokensForETH(
        address tokenIn,
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline,
        uint8 flag
    ) external returns (uint256[] memory amounts);

    function swapETHForExactTokens(
        address tokenOut,
        uint256 amountOut,
        address[] calldata path,
        address to,
        uint256 deadline,
        uint8 flag
    ) external payable returns (uint256[] memory amounts);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        address tokenIn,
        address tokenOut,
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline,
        uint8 flag
    ) external;

    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        address tokenOut,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline,
        uint8 flag
    ) external payable;

    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        address tokenIn,
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline,
        uint8 flag
    ) external;

    function addStakeLiquidity(
        address stakePool,
        address tokenA,
        address tokenB,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin,
        uint256 deadline
    )
        external
        returns (
            uint256 amountA,
            uint256 amountB,
            uint256 liquidity
        );

    function addStakeLiquidityETH(
        address stakePool,
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        uint256 deadline
    )
        external
        payable
        returns (
            uint256 amountToken,
            uint256 amountETH,
            uint256 liquidity
        );

    function multihopBatchSwapExactIn(
        Swap[][] memory swapSequences,
        address tokenIn,
        address tokenOut,
        uint256 totalAmountIn,
        uint256 minTotalAmountOut,
        uint256 deadline,
        uint8 flag
    ) external payable returns (uint256 totalAmountOut);

    function multihopBatchSwapExactOut(
        Swap[][] memory swapSequences,
        address tokenIn,
        address tokenOut,
        uint256 maxTotalAmountIn,
        uint256 deadline,
        uint8 flag
    ) external payable returns (uint256 totalAmountIn);

    function createPair(
        address tokenA,
        address tokenB,
        uint256 amountA,
        uint256 amountB,
        uint32 tokenWeightA,
        uint32 swapFee,
        address to,
        uint8 flag
    ) external returns (uint256 liquidity);

    function createPairETH(
        address token,
        uint256 amountToken,
        uint32 tokenWeight,
        uint32 swapFee,
        address to,
        uint8 flag
    ) external payable returns (uint256 liquidity);
}

interface IValueLiquidFactory {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint32 tokenWeight0, uint32 swapFee, uint256);

    function feeTo() external view returns (address);

    function formula() external view returns (address);

    function protocolFee() external view returns (uint256);

    function feeToSetter() external view returns (address);

    function getPair(
        address tokenA,
        address tokenB,
        uint32 tokenWeightA,
        uint32 swapFee
    ) external view returns (address pair);

    function allPairs(uint256) external view returns (address pair);

    function isPair(address) external view returns (bool);

    function allPairsLength() external view returns (uint256);

    function createPair(
        address tokenA,
        address tokenB,
        uint32 tokenWeightA,
        uint32 swapFee
    ) external returns (address pair);

    function getWeightsAndSwapFee(address pair)
        external
        view
        returns (
            uint32 tokenWeight0,
            uint32 tokenWeight1,
            uint32 swapFee
        );

    function setFeeTo(address) external;

    function setFeeToSetter(address) external;

    function setProtocolFee(uint256) external;
}

// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
    function safeApprove(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: APPROVE_FAILED");
    }

    function safeTransfer(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: TRANSFER_FAILED");
    }

    function safeTransferFrom(
        address token,
        address from,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: TRANSFER_FROM_FAILED");
    }

    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, "TransferHelper: ETH_TRANSFER_FAILED");
    }
}

interface IValueLiquidPair {
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Transfer(address indexed from, address indexed to, uint256 value);

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

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

    function decimals() external pure returns (uint8);

    function totalSupply() external view returns (uint256);

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

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

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

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

    function nonces(address owner) external view returns (uint256);

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    event PaidProtocolFee(uint112 collectedFee0, uint112 collectedFee1);
    event Mint(address indexed sender, uint256 amount0, uint256 amount1);
    event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);
    event Swap(address indexed sender, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out, address indexed to);
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint256);

    function factory() external view returns (address);

    function token0() external view returns (address);

    function token1() external view returns (address);

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

    function getCollectedFees() external view returns (uint112 _collectedFee0, uint112 _collectedFee1);

    function getTokenWeights() external view returns (uint32 tokenWeight0, uint32 tokenWeight1);

    function getSwapFee() external view returns (uint32);

    function price0CumulativeLast() external view returns (uint256);

    function price1CumulativeLast() external view returns (uint256);

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

    function burn(address to) external returns (uint256 amount0, uint256 amount1);

    function swap(
        uint256 amount0Out,
        uint256 amount1Out,
        address to,
        bytes calldata data
    ) external;

    function skim(address to) external;

    function sync() external;

    function initialize(
        address,
        address,
        uint32,
        uint32
    ) external;
}

// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
library SafeMath {
    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
        require((z = x + y) >= x, "ds-math-add-overflow");
    }

    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
        require((z = x - y) <= x, "ds-math-sub-underflow");
    }

    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256 c) {
        require(b > 0, "ds-math-division-by-zero");
        c = a / b;
    }
}

contract TimeLock {
    using SafeMath for uint256;
    event NewAdmin(address indexed newAdmin);
    event NewPendingAdmin(address indexed newPendingAdmin);
    event NewDelay(uint256 indexed newDelay);
    event CancelTransaction(bytes32 indexed txHash, address indexed target, uint256 value, string signature, bytes data, uint256 eta);
    event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint256 value, string signature, bytes data, uint256 eta);
    event QueueTransaction(bytes32 indexed txHash, address indexed target, uint256 value, string signature, bytes data, uint256 eta);

    uint256 public constant GRACE_PERIOD = 14 days;
    uint256 public constant MINIMUM_DELAY = 1 days;
    uint256 public constant MAXIMUM_DELAY = 30 days;
    bool private _initialized;
    address public admin;
    address public pendingAdmin;
    uint256 public delay;
    bool public admin_initialized;
    mapping(bytes32 => bool) public queuedTransactions;

    constructor() {
        admin_initialized = false;
        _initialized = false;
    }

    function initialize(address _admin, uint256 _delay) public {
        require(_initialized == false, "Timelock::constructor: Initialized must be false.");
        require(_delay >= MINIMUM_DELAY, "Timelock::setDelay: Delay must exceed minimum delay.");
        require(_delay <= MAXIMUM_DELAY, "Timelock::setDelay: Delay must not exceed maximum delay.");
        delay = _delay;
        admin = _admin;
        _initialized = true;
        emit NewAdmin(admin);
        emit NewDelay(delay);
    }

    receive() external payable {}

    function setDelay(uint256 _delay) public {
        require(msg.sender == address(this), "Timelock::setDelay: Call must come from Timelock.");
        require(_delay >= MINIMUM_DELAY, "Timelock::setDelay: Delay must exceed minimum delay.");
        require(_delay <= MAXIMUM_DELAY, "Timelock::setDelay: Delay must not exceed maximum delay.");
        delay = _delay;
        emit NewDelay(delay);
    }

    function acceptAdmin() public {
        require(msg.sender == pendingAdmin, "Timelock::acceptAdmin: Call must come from pendingAdmin.");
        admin = msg.sender;
        pendingAdmin = address(0);
        emit NewAdmin(admin);
    }

    function setPendingAdmin(address _pendingAdmin) public {
        // allows one time setting of admin for deployment purposes
        if (admin_initialized) {
            require(msg.sender == address(this), "Timelock::setPendingAdmin: Call must come from Timelock.");
        } else {
            require(msg.sender == admin, "Timelock::setPendingAdmin: First call must come from admin.");
            admin_initialized = true;
        }
        pendingAdmin = _pendingAdmin;

        emit NewPendingAdmin(pendingAdmin);
    }

    function queueTransaction(
        address target,
        uint256 value,
        string memory signature,
        bytes memory data,
        uint256 eta
    ) public returns (bytes32) {
        require(msg.sender == admin, "Timelock::queueTransaction: Call must come from admin.");
        require(eta >= getBlockTimestamp().add(delay), "Timelock::queueTransaction: Estimated execution block must satisfy delay.");

        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));
        queuedTransactions[txHash] = true;

        emit QueueTransaction(txHash, target, value, signature, data, eta);
        return txHash;
    }

    function cancelTransaction(
        address target,
        uint256 value,
        string memory signature,
        bytes memory data,
        uint256 eta
    ) public {
        require(msg.sender == admin, "Timelock::cancelTransaction: Call must come from admin.");

        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));
        queuedTransactions[txHash] = false;

        emit CancelTransaction(txHash, target, value, signature, data, eta);
    }

    function executeTransaction(
        address target,
        uint256 value,
        string memory signature,
        bytes memory data,
        uint256 eta
    ) public payable returns (bytes memory) {
        require(msg.sender == admin, "Timelock::executeTransaction: Call must come from admin.");

        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));
        require(queuedTransactions[txHash], "Timelock::executeTransaction: Transaction hasn't been queued.");
        require(getBlockTimestamp() >= eta, "Timelock::executeTransaction: Transaction hasn't surpassed time lock.");
        require(getBlockTimestamp() <= eta.add(GRACE_PERIOD), "Timelock::executeTransaction: Transaction is stale.");

        queuedTransactions[txHash] = false;

        bytes memory callData;

        if (bytes(signature).length == 0) {
            callData = data;
        } else {
            callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);
        }

        // solium-disable-next-line security/no-call-value
        (bool success, bytes memory returnData) = target.call{value: value}(callData);
        require(success, "Timelock::executeTransaction: Transaction execution reverted.");

        emit ExecuteTransaction(txHash, target, value, signature, data, eta);

        return returnData;
    }

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

interface IEpochController {
    function epoch() external view returns (uint256);

    function nextEpochPoint() external view returns (uint256);

    function nextEpochLength() external view returns (uint256);

    function nextEpochAllocatedReward(address _pool) external view returns (uint256);
}

interface IStakePoolEpochReward {
    event AllocateReward(uint256 blocktime, uint256 amount);
    event Deposit(address indexed account, uint256 amount);
    event PayRewardPool(
        uint256 indexed poolId,
        address indexed rewardToken,
        address indexed account,
        uint256 pendingReward,
        uint256 rebaseAmount,
        uint256 paidReward
    );
    event Withdraw(address indexed account, uint256 amount);

    function version() external returns (uint256);

    function pair() external returns (address);

    function allowRecoverRewardToken(address _token) external view returns (bool);

    function epoch() external view returns (uint256);

    function nextEpochPoint() external view returns (uint256);

    function nextEpochLength() external view returns (uint256);

    function nextEpochAllocatedReward() external view returns (uint256);

    function earned(address _account) external view returns (uint256);

    function unlockWithdrawEpoch(address _account) external view returns (uint256);

    function unlockRewardEpoch(address _account) external view returns (uint256);

    function stake(uint256) external;

    function stakeFor(address _account) external;

    function withdraw(uint256) external;

    function claimReward() external;

    function emergencyWithdraw() external;

    function setEpochController(address) external;

    function setLockUp(uint256 _withdrawLockupEpochs, uint256 _rewardLockupEpochs) external;

    function allocateReward(uint256 _amount) external;

    function removeLiquidity(
        address provider,
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETH(
        address provider,
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountToken, uint256 amountETH);

    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address provider,
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountETH);
}

interface IValueLiquidProvider {
    function factory() external view returns (address);

    function controller() external view returns (address);

    function formula() external view returns (address);

    function WETH() external view returns (address);

    function removeLiquidity(
        address pair,
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETH(
        address pair,
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountToken, uint256 amountETH);

    function removeLiquidityWithPermit(
        address pair,
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETHWithPermit(
        address pair,
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountToken, uint256 amountETH);

    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address pair,
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountETH);

    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address pair,
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountETH);

    function stake(
        address stakePool,
        uint256 amount,
        uint256 deadline
    ) external;

    function stakeWithPermit(
        address stakePool,
        uint256 amount,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

interface IStakePoolController {
    event MasterCreated(address indexed farm, address indexed pair, uint256 version, address timelock, address stakePoolRewardFund, uint256 totalStakePool);
    event SetWhitelistStakingFor(address indexed contractAddress, bool value);
    event SetWhitelistStakePool(address indexed contractAddress, int8 value);
    event SetStakePoolCreator(address indexed contractAddress, uint256 verion);
    event SetWhitelistRewardRebaser(address indexed contractAddress, bool value);
    event SetWhitelistRewardMultiplier(address indexed contractAddress, bool value);
    event SetStakePoolVerifier(address indexed contractAddress, bool value);
    event ChangeGovernance(address indexed governance);
    event SetFeeCollector(address indexed feeCollector);
    event SetFeeToken(address indexed token);
    event SetFeeAmount(uint256 indexed amount);

    function allStakePools(uint256) external view returns (address stakePool);

    function isStakePool(address contractAddress) external view returns (bool);

    function isStakePoolVerifier(address contractAddress) external view returns (bool);

    function isWhitelistStakingFor(address contractAddress) external view returns (bool);

    function isWhitelistStakePool(address contractAddress) external view returns (int8);

    function setStakePoolVerifier(address contractAddress, bool state) external;

    function setWhitelistStakingFor(address contractAddress, bool state) external;

    function setWhitelistStakePool(address contractAddress, int8 state) external;

    function addStakePoolCreator(address contractAddress) external;

    function isWhitelistRewardRebaser(address contractAddress) external view returns (bool);

    function isAllowEmergencyWithdrawStakePool(address _address) external view returns (bool);

    function setWhitelistRewardRebaser(address contractAddress, bool state) external;

    function isWhitelistRewardMultiplier(address contractAddress) external view returns (bool);

    function setAllowEmergencyWithdrawStakePool(address _address, bool state) external;

    function setWhitelistRewardMultiplier(address contractAddress, bool state) external;

    function setEnableWhitelistRewardRebaser(bool value) external;

    function setEnableWhitelistRewardMultiplier(bool value) external;

    function allStakePoolsLength() external view returns (uint256);

    function create(
        uint256 version,
        address pair,
        address rewardToken,
        uint256 rewardFundAmount,
        uint256 delayTimeLock,
        bytes calldata data,
        uint8 flag
    ) external returns (address);

    function createPair(
        uint256 version,
        address tokenA,
        address tokenB,
        uint32 tokenWeightA,
        uint32 swapFee,
        address rewardToken,
        uint256 rewardFundAmount,
        uint256 delayTimeLock,
        bytes calldata poolRewardInfo,
        uint8 flag
    ) external returns (address);

    function setGovernance(address) external;

    function setFeeCollector(address _address) external;

    function setFeeToken(address _token) external;

    function setFeeAmount(uint256 _token) external;
}

interface IStakePoolRewardRebaser {
    function getRebaseAmount(address rewardToken, uint256 baseAmount) external view returns (uint256);
}

interface IStakePoolRewardMultiplier {
    function getRewardMultiplier(
        uint256 _start,
        uint256 _end,
        uint256 _from,
        uint256 _to,
        uint256 _rewardPerBlock
    ) external view returns (uint256);
}

interface IERC20 {
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Transfer(address indexed from, address indexed to, uint256 value);

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

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

    function decimals() external view returns (uint8);

    function totalSupply() external view returns (uint256);

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

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

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

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);
}

interface IStakePoolRewardFund {
    function initialize(address _stakePool, address _timelock) external;

    function safeTransfer(
        address _token,
        address _to,
        uint256 _value
    ) external;
}

// This implements BPool contract, and allows for generalized staking, yield farming (by epoch), and token distribution.
contract StakePoolEpochReward is IStakePoolEpochReward {
    using SafeMath for uint256;
    uint256 public override version;

    /* ========== DATA STRUCTURES ========== */

    struct UserInfo {
        uint256 amount;
        uint256 lastSnapshotIndex;
        uint256 rewardEarned;
        uint256 epochTimerStart;
    }

    struct Snapshot {
        uint256 time;
        uint256 rewardReceived;
        uint256 rewardPerShare;
    }

    /* ========== STATE VARIABLES ========== */

    address public epochController;
    address public rewardToken;

    uint256 public withdrawLockupEpochs;
    uint256 public rewardLockupEpochs;

    mapping(address => UserInfo) public userInfo;
    Snapshot[] public snapshotHistory;

    address public override pair;
    address public rewardFund;
    address public timelock;
    address public controller;

    uint256 public balance;
    uint256 private _unlocked = 1;
    bool private _initialized = false;

    constructor(address _controller, uint256 _version) {
        controller = _controller;
        timelock = msg.sender;
        version = _version;
        Snapshot memory genesisSnapshot = Snapshot({time: block.number, rewardReceived: 0, rewardPerShare: 0});
        snapshotHistory.push(genesisSnapshot);
    }

    modifier lock() {
        require(_unlocked == 1, "StakePoolEpochReward: LOCKED");
        _unlocked = 0;
        _;
        _unlocked = 1;
    }

    modifier onlyTimeLock() {
        require(msg.sender == timelock, "StakePoolEpochReward: !timelock");
        _;
    }

    modifier onlyEpochController() {
        require(msg.sender == epochController, "StakePoolEpochReward: !epochController");
        _;
    }

    modifier updateReward(address _account) {
        if (_account != address(0)) {
            UserInfo storage user = userInfo[_account];
            user.rewardEarned = earned(_account);
            user.lastSnapshotIndex = latestSnapshotIndex();
        }
        _;
    }

    // called once by the factory at time of deployment
    function initialize(
        address _pair,
        address _rewardFund,
        address _timelock,
        address _epochController,
        address _rewardToken,
        uint256 _withdrawLockupEpochs,
        uint256 _rewardLockupEpochs
    ) external {
        require(_initialized == false, "StakePoolEpochReward: Initialize must be false.");
        pair = _pair;
        rewardFund = _rewardFund;
        timelock = _timelock;
        withdrawLockupEpochs = _withdrawLockupEpochs;
        rewardLockupEpochs = _rewardLockupEpochs;
        epochController = _epochController;
        rewardToken = _rewardToken;
        _initialized = true;
    }

    /* ========== GOVERNANCE ========== */

    function setEpochController(address _epochController) external override lock onlyTimeLock {
        epochController = _epochController;
    }

    function setLockUp(uint256 _withdrawLockupEpochs, uint256 _rewardLockupEpochs) external override lock onlyTimeLock {
        require(_withdrawLockupEpochs >= _rewardLockupEpochs && _withdrawLockupEpochs <= 56, "_withdrawLockupEpochs: out of range"); // <= 2 week
        withdrawLockupEpochs = _withdrawLockupEpochs;
        rewardLockupEpochs = _rewardLockupEpochs;
    }

    function allocateReward(uint256 _amount) external override lock onlyEpochController {
        require(_amount > 0, "StakePoolEpochReward: Cannot allocate 0");
        uint256 _before = IERC20(rewardToken).balanceOf(address(rewardFund));
        TransferHelper.safeTransferFrom(rewardToken, msg.sender, rewardFund, _amount);
        if (balance > 0) {
            uint256 _after = IERC20(rewardToken).balanceOf(address(rewardFund));
            _amount = _after.sub(_before);

            // Create & add new snapshot
            uint256 _prevRPS = getLatestSnapshot().rewardPerShare;
            uint256 _nextRPS = _prevRPS.add(_amount.mul(1e18).div(balance));

            Snapshot memory _newSnapshot = Snapshot({time: block.number, rewardReceived: _amount, rewardPerShare: _nextRPS});
            emit AllocateReward(block.number, _amount);
            snapshotHistory.push(_newSnapshot);
        }
    }

    function allowRecoverRewardToken(address _token) external view override returns (bool) {
        if (rewardToken == _token) {
            // do not allow to drain reward token if less than 1 months after pool ends
            if (block.timestamp < (getLatestSnapshot().time + 7 days)) {
                return false;
            }
        }
        return true;
    }

    // =========== Epoch getters

    function epoch() public view override returns (uint256) {
        return IEpochController(epochController).epoch();
    }

    function nextEpochPoint() external view override returns (uint256) {
        return IEpochController(epochController).nextEpochPoint();
    }

    function nextEpochLength() external view override returns (uint256) {
        return IEpochController(epochController).nextEpochLength();
    }

    function nextEpochAllocatedReward() external view override returns (uint256) {
        return IEpochController(epochController).nextEpochAllocatedReward(address(this));
    }

    // =========== Snapshot getters

    function latestSnapshotIndex() public view returns (uint256) {
        return snapshotHistory.length.sub(1);
    }

    function getLatestSnapshot() internal view returns (Snapshot memory) {
        return snapshotHistory[latestSnapshotIndex()];
    }

    function getLastSnapshotIndexOf(address _account) public view returns (uint256) {
        return userInfo[_account].lastSnapshotIndex;
    }

    function getLastSnapshotOf(address _account) internal view returns (Snapshot memory) {
        return snapshotHistory[getLastSnapshotIndexOf(_account)];
    }

    // =========== _account getters

    function rewardPerShare() public view returns (uint256) {
        return getLatestSnapshot().rewardPerShare;
    }

    function earned(address _account) public view override returns (uint256) {
        uint256 latestRPS = getLatestSnapshot().rewardPerShare;
        uint256 storedRPS = getLastSnapshotOf(_account).rewardPerShare;

        UserInfo memory user = userInfo[_account];
        return user.amount.mul(latestRPS.sub(storedRPS)).div(1e18).add(user.rewardEarned);
    }

    function canWithdraw(address _account) external view returns (bool) {
        return userInfo[_account].epochTimerStart.add(withdrawLockupEpochs) <= epoch();
    }

    function canClaimReward(address _account) external view returns (bool) {
        return userInfo[_account].epochTimerStart.add(rewardLockupEpochs) <= epoch();
    }

    function unlockWithdrawEpoch(address _account) public view override returns (uint256) {
        return userInfo[_account].epochTimerStart.add(withdrawLockupEpochs);
    }

    function unlockRewardEpoch(address _account) public view override returns (uint256) {
        return userInfo[_account].epochTimerStart.add(rewardLockupEpochs);
    }

    /* ========== MUTATIVE FUNCTIONS ========== */

    function stake(uint256 _amount) external override lock {
        IValueLiquidPair(pair).transferFrom(msg.sender, address(this), _amount);
        _stakeFor(msg.sender);
    }

    function stakeFor(address _account) external override lock {
        require(IStakePoolController(controller).isWhitelistStakingFor(msg.sender), "StakePoolEpochReward: Invalid sender");
        _stakeFor(_account);
    }

    function _stakeFor(address _account) internal {
        uint256 _amount = IValueLiquidPair(pair).balanceOf(address(this)).sub(balance);
        require(_amount > 0, "StakePoolEpochReward: Invalid balance");
        balance = balance.add(_amount);
        UserInfo storage user = userInfo[_account];
        user.epochTimerStart = epoch(); // reset timer
        user.amount = user.amount.add(_amount);
        emit Deposit(_account, _amount);
    }

    function removeStakeInternal(uint256 _amount) internal {
        UserInfo storage user = userInfo[msg.sender];
        uint256 _epoch = epoch();
        require(user.epochTimerStart.add(withdrawLockupEpochs) <= _epoch, "StakePoolEpochReward: still in withdraw lockup");
        require(user.amount >= _amount, "StakePoolEpochReward: invalid withdraw amount");
        _claimReward(false);
        balance = balance.sub(_amount);
        user.epochTimerStart = _epoch; // reset timer
        user.amount = user.amount.sub(_amount);
    }

    function withdraw(uint256 _amount) public override lock {
        removeStakeInternal(_amount);
        IValueLiquidPair(pair).transfer(msg.sender, _amount);
        emit Withdraw(msg.sender, _amount);
    }

    function exit() external {
        withdraw(userInfo[msg.sender].amount);
    }

    function _claimReward(bool _lockChecked) internal updateReward(msg.sender) {
        UserInfo storage user = userInfo[msg.sender];
        uint256 _reward = user.rewardEarned;
        if (_reward > 0) {
            if (_lockChecked) {
                uint256 _epoch = epoch();
                require(user.epochTimerStart.add(rewardLockupEpochs) <= _epoch, "StakePoolEpochReward: still in reward lockup");
                user.epochTimerStart = _epoch; // reset timer
            }
            user.rewardEarned = 0;
            // Safe reward transfer, just in case if rounding error causes pool to not have enough reward amount
            uint256 _rewardBalance = IERC20(rewardToken).balanceOf(rewardFund);
            uint256 _paidAmount = _rewardBalance > _reward ? _reward : _rewardBalance;
            IStakePoolRewardFund(rewardFund).safeTransfer(rewardToken, msg.sender, _paidAmount);
            emit PayRewardPool(0, rewardToken, msg.sender, _reward, _reward, _paidAmount);
        }
    }

    function claimReward() public override {
        _claimReward(true);
    }

    // Withdraw without caring about rewards. EMERGENCY ONLY.
    function emergencyWithdraw() external override lock {
        require(IStakePoolController(controller).isAllowEmergencyWithdrawStakePool(address(this)), "StakePoolEpochReward: Not allow emergencyWithdraw");
        UserInfo storage user = userInfo[msg.sender];
        uint256 amount = user.amount;
        balance = balance.sub(amount);
        user.amount = 0;
        IValueLiquidPair(pair).transfer(msg.sender, amount);
    }

    function removeLiquidity(
        address provider,
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    ) public override lock returns (uint256 amountA, uint256 amountB) {
        require(IStakePoolController(controller).isWhitelistStakingFor(provider), "StakePoolEpochReward: Invalid provider");
        removeStakeInternal(liquidity);
        IValueLiquidPair(pair).approve(provider, liquidity);
        emit Withdraw(msg.sender, liquidity);
        (amountA, amountB) = IValueLiquidProvider(provider).removeLiquidity(address(pair), tokenA, tokenB, liquidity, amountAMin, amountBMin, to, deadline);
    }

    function removeLiquidityETH(
        address provider,
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external override lock returns (uint256 amountToken, uint256 amountETH) {
        require(IStakePoolController(controller).isWhitelistStakingFor(provider), "StakePoolEpochReward: Invalid provider");
        removeStakeInternal(liquidity);
        IValueLiquidPair(pair).approve(provider, liquidity);
        emit Withdraw(msg.sender, liquidity);
        (amountToken, amountETH) = IValueLiquidProvider(provider).removeLiquidityETH(
            address(pair),
            token,
            liquidity,
            amountTokenMin,
            amountETHMin,
            to,
            deadline
        );
    }

    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address provider,
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external override lock returns (uint256 amountETH) {
        require(IStakePoolController(controller).isWhitelistStakingFor(provider), "StakePoolEpochReward: Invalid provider");
        removeStakeInternal(liquidity);
        IValueLiquidPair(pair).approve(provider, liquidity);
        emit Withdraw(msg.sender, liquidity);
        amountETH = IValueLiquidProvider(provider).removeLiquidityETHSupportingFeeOnTransferTokens(
            address(pair),
            token,
            liquidity,
            amountTokenMin,
            amountETHMin,
            to,
            deadline
        );
    }
}

contract StakePoolEpochRewardCreator is IStakePoolCreator {
    uint256 public override version = 4001;
    struct PoolRewardInfo {
        address epochController;
        uint256 withdrawLockupEpochs;
        uint256 rewardLockupEpochs;
    }

    function create() external override returns (address) {
        StakePoolEpochReward pool = new StakePoolEpochReward(msg.sender, version);
        return address(pool);
    }

    function initialize(
        address poolAddress,
        address pair,
        address rewardToken,
        address timelock,
        address stakePoolRewardFund,
        bytes calldata data
    ) external override {
        StakePoolEpochReward pool = StakePoolEpochReward(poolAddress);

        PoolRewardInfo memory poolRewardInfo = abi.decode(data, (PoolRewardInfo));
        pool.initialize(
            pair,
            address(stakePoolRewardFund),
            address(timelock),
            poolRewardInfo.epochController,
            rewardToken,
            poolRewardInfo.withdrawLockupEpochs,
            poolRewardInfo.rewardLockupEpochs
        );
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"name":"create","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"address","name":"pair","type":"address"},{"internalType":"address","name":"rewardToken","type":"address"},{"internalType":"address","name":"timelock","type":"address"},{"internalType":"address","name":"stakePoolRewardFund","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

6080604052610fa160005534801561001657600080fd5b506135c0806100266000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806301f79fb61461004657806354fd4d501461005b578063efc81a8c14610079575b600080fd5b6100596100543660046101aa565b61008e565b005b61006361012d565b604051610070919061035c565b60405180910390f35b610081610133565b60405161007091906102c5565b86600061009d8385018561026b565b90508173ffffffffffffffffffffffffffffffffffffffff1663b33f952789878985600001518c876020015188604001516040518863ffffffff1660e01b81526004016100f0979695949392919061030c565b600060405180830381600087803b15801561010a57600080fd5b505af115801561011e573d6000803e3d6000fd5b50505050505050505050505050565b60005481565b6000803360005460405161014690610174565b6101519291906102e6565b604051809103906000f08015801561016d573d6000803e3d6000fd5b5091505090565b6132258061036683390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146101a557600080fd5b919050565b600080600080600080600060c0888a0312156101c4578283fd5b6101cd88610181565b96506101db60208901610181565b95506101e960408901610181565b94506101f760608901610181565b935061020560808901610181565b925060a088013567ffffffffffffffff80821115610221578384fd5b818a0191508a601f830112610234578384fd5b813581811115610242578485fd5b8b6020828501011115610253578485fd5b60208301945080935050505092959891949750929550565b60006060828403121561027c578081fd5b6040516060810181811067ffffffffffffffff8211171561029957fe5b6040526102a583610181565b815260208301356020820152604083013560408201528091505092915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9788168152958716602087015293861660408601529185166060850152909316608083015260a082019290925260c081019190915260e00190565b9081526020019056fe60806040526001600c55600d805460ff191690553480156200002057600080fd5b506040516200322538038062003225833981016040819052620000439162000118565b600a80546001600160a01b039093166001600160a01b031993841617905560098054909216331790915560009081556040805160608101825243815260208101838152918101838152600680546001810182559452905160039093027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f81019390935590517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40830155517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d419091015562000152565b600080604083850312156200012b578182fd5b82516001600160a01b038116811462000142578283fd5b6020939093015192949293505050565b6130c380620001626000396000f3fe608060405234801561001057600080fd5b50600436106102915760003560e01c8063714b465811610160578063d33219b4116100d8578063e9fad8ee1161008c578063efe2226611610071578063efe22266146104de578063f77c4791146104e6578063f7c618c1146104ee57610291565b8063e9fad8ee146104c3578063ebb5d2e9146104cb57610291565b8063e1f4a784116100bd578063e1f4a7841461048a578063e2dcb6161461049d578063e7d80e31146104b057610291565b8063d33219b41461047a578063db2e21bc1461048257610291565b8063b33f95271161012f578063b69ef8a811610114578063b69ef8a814610462578063b88a802f1461046a578063c5967c261461047257610291565b8063b33f95271461042e578063b56b681d1461044157610291565b8063714b4658146103f8578063900cf0cf1461040b578063a694fc3a14610413578063a8aa1b311461042657610291565b8063224556181161020e578063446a2ec8116101c257806354fd4d50116101a757806354fd4d50146103ca5780635a9c0644146103d257806362e7e463146103e557610291565b8063446a2ec8146103af5780634bf69206146103b757610291565b80632ffaaa09116101f35780632ffaaa09146103815780633468a5b8146103945780633f9e3f04146103a757610291565b806322455618146103645780632e1a7d4d1461036c57610291565b806307284ce91161026557806319262d301161024a57806319262d30146103265780631959a002146103395780631e85cd651461035c57610291565b806307284ce9146102fc57806311815a391461030457610291565b80628cc26214610296578063022ba18d146102bf57806303df4868146102c7578063046335d0146102dc575b600080fd5b6102a96102a4366004612731565b6104f6565b6040516102b69190613045565b60405180910390f35b6102a96105ab565b6102cf6105b1565b6040516102b69190612979565b6102ef6102ea366004612731565b6105cd565b6040516102b69190612a94565b6102a9610614565b6103176103123660046128cc565b6106bc565b6040516102b69392919061305c565b6102ef610334366004612731565b6106ef565b61034c610347366004612731565b61072f565b6040516102b69493929190613072565b6102a9610756565b6102a961075c565b61037f61037a3660046128cc565b6107cb565b005b61037f61038f3660046128fc565b61091f565b6102ef6103a2366004612731565b610a08565b6102a9610a53565b6102a9610a64565b61037f6103c5366004612731565b610a77565b6102a9610ba5565b61037f6103e0366004612731565b610bab565b6102a96103f3366004612731565b610c87565b6102a9610406366004612731565b610cc5565b6102a9610cf0565b61037f6104213660046128cc565b610d5b565b6102cf610e52565b61037f61043c366004612752565b610e6e565b61045461044f366004612843565b610f62565b6040516102b692919061304e565b6102a961124e565b61037f611254565b6102a9611260565b6102cf6112cb565b61037f6112e7565b6104546104983660046127c9565b6114dd565b61037f6104ab3660046128cc565b6117cc565b6102a96104be366004612731565b611b6d565b61037f611ba3565b6102a96104d9366004612843565b611bbc565b6102cf611ea4565b6102cf611ec0565b6102cf611edc565b600080610501611ef8565b604001519050600061051284611f50565b60409081015173ffffffffffffffffffffffffffffffffffffffff8616600090815260056020908152908390208351608081018552815481526001820154928101929092526002810154938201849052600301546060820152909250906105a09061059a670de0b6b3a764000061059461058c8888611fab565b865190611fe8565b90612039565b90612085565b93505050505b919050565b60045481565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60006105d7610cf0565b60045473ffffffffffffffffffffffffffffffffffffffff841660009081526005602052604090206003015461060c91612085565b111592915050565b600154604080517f07284ce9000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916307284ce9916004808301926020929190829003018186803b15801561067f57600080fd5b505afa158015610693573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b791906128e4565b905090565b600681815481106106cc57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b60006106f9610cf0565b6003805473ffffffffffffffffffffffffffffffffffffffff851660009081526005602052604090209091015461060c91612085565b60056020526000908152604090208054600182015460028301546003909301549192909184565b60035481565b6001546040517f7effa5b600000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff1690637effa5b6906107b3903090600401612979565b60206040518083038186803b15801561067f57600080fd5b600c54600114610810576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b60405180910390fd5b6000600c5561081e816120c2565b6007546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063a9059cbb9061087690339085906004016129cb565b602060405180830381600087803b15801561089057600080fd5b505af11580156108a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c891906128ac565b503373ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648260405161090f9190613045565b60405180910390a2506001600c55565b600c5460011461095b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c5560095473ffffffffffffffffffffffffffffffffffffffff1633146109b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612dcf565b8082101580156109c2575060388211155b6109f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612d72565b6003919091556004556001600c55565b60025460009073ffffffffffffffffffffffffffffffffffffffff83811691161415610a4b57610a36611ef8565b5162093a8001421015610a4b575060006105a6565b506001919050565b6006546000906106b7906001611fab565b6000610a6e611ef8565b60400151905090565b600c54600114610ab3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c55600a546040517f393a748400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063393a748490610b0e903390600401612979565b60206040518083038186803b158015610b2657600080fd5b505afa158015610b3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5e91906128ac565b610b94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612d15565b610b9d8161219d565b506001600c55565b60005481565b600c54600114610be7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c5560095473ffffffffffffffffffffffffffffffffffffffff163314610c3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612dcf565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091178155600c55565b60045473ffffffffffffffffffffffffffffffffffffffff82166000908152600560205260408120600301549091610cbf9190612085565b92915050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526005602052604090206001015490565b600154604080517f900cf0cf000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163900cf0cf916004808301926020929190829003018186803b15801561067f57600080fd5b600c54600114610d97576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c556007546040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd90610df69033903090869060040161299a565b602060405180830381600087803b158015610e1057600080fd5b505af1158015610e24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4891906128ac565b50610b9d3361219d565b60075473ffffffffffffffffffffffffffffffffffffffff1681565b600d5460ff1615610eab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612ec0565b600780547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff998a161790915560088054821697891697909717909655600980548716958816959095179094556003556004929092556001805484169185169190911781556002805490931691909316179055600d80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169091179055565b600080600c54600114610fa1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c55600a546040517f393a748400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063393a748490610ffc908c90600401612979565b60206040518083038186803b15801561101457600080fd5b505afa158015611028573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104c91906128ac565b611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612ba1565b61108b876120c2565b6007546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063095ea7b3906110e3908c908b906004016129cb565b602060405180830381600087803b1580156110fd57600080fd5b505af1158015611111573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113591906128ac565b503373ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648860405161117c9190613045565b60405180910390a26007546040517fb56b681d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81169263b56b681d926111e892909116908c908c908c908c908c908c90600401612a47565b6040805180830381600087803b15801561120157600080fd5b505af1158015611215573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611239919061291d565b6001600c55909a909950975050505050505050565b600b5481565b61125e6001612336565b565b600154604080517fc5967c26000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163c5967c26916004808301926020929190829003018186803b15801561067f57600080fd5b60095473ffffffffffffffffffffffffffffffffffffffff1681565b600c54600114611323576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c55600a546040517fea74109e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063ea74109e9061137e903090600401612979565b60206040518083038186803b15801561139657600080fd5b505afa1580156113aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ce91906128ac565b611404576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612e06565b3360009081526005602052604090208054600b546114229082611fab565b600b55600082556007546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063a9059cbb9061148190339085906004016129cb565b602060405180830381600087803b15801561149b57600080fd5b505af11580156114af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d391906128ac565b50506001600c5550565b600080600c5460011461151c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c55600a546040517f393a748400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063393a748490611577908d90600401612979565b60206040518083038186803b15801561158f57600080fd5b505afa1580156115a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c791906128ac565b6115fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612ba1565b611606876120c2565b6007546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063095ea7b39061165e908d908b906004016129cb565b602060405180830381600087803b15801561167857600080fd5b505af115801561168c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b091906128ac565b503373ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364886040516116f79190613045565b60405180910390a26007546040517fe1f4a78400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81169263e1f4a7849261176592909116908d908d908d908d908d908d908d906004016129f1565b6040805180830381600087803b15801561177e57600080fd5b505af1158015611792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b6919061291d565b6001600c55909b909a5098505050505050505050565b600c54600114611808576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c5560015473ffffffffffffffffffffffffffffffffffffffff16331461185e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612bfe565b60008111611898576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612c5b565b6002546008546040517f70a0823100000000000000000000000000000000000000000000000000000000815260009273ffffffffffffffffffffffffffffffffffffffff908116926370a08231926118f69290911690600401612979565b60206040518083038186803b15801561190e57600080fd5b505afa158015611922573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194691906128e4565b6002546008549192506119759173ffffffffffffffffffffffffffffffffffffffff91821691339116856125c0565b600b5415611b64576002546008546040517f70a0823100000000000000000000000000000000000000000000000000000000815260009273ffffffffffffffffffffffffffffffffffffffff908116926370a08231926119db9290911690600401612979565b60206040518083038186803b1580156119f357600080fd5b505afa158015611a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2b91906128e4565b9050611a378183611fab565b92506000611a43611ef8565b6040015190506000611a76611a6f600b54610594670de0b6b3a764000089611fe890919063ffffffff16565b8390612085565b9050600060405180606001604052804381526020018781526020018381525090507fae0e1452e3105698745005d16edaee897b9daf225b8434ea419008b58e60cb764387604051611ac892919061304e565b60405180910390a16006805460018101825560009190915281517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f60039092029182015560208201517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d408201556040909101517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d41909101555050505b50506001600c55565b6003805473ffffffffffffffffffffffffffffffffffffffff8316600090815260056020526040812090920154610cbf91612085565b3360009081526005602052604090205461125e906107cb565b6000600c54600114611bfa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c55600a546040517f393a748400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063393a748490611c55908b90600401612979565b60206040518083038186803b158015611c6d57600080fd5b505afa158015611c81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca591906128ac565b611cdb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612ba1565b611ce4866120c2565b6007546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063095ea7b390611d3c908b908a906004016129cb565b602060405180830381600087803b158015611d5657600080fd5b505af1158015611d6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8e91906128ac565b503373ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436487604051611dd59190613045565b60405180910390a26007546040517febb5d2e900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a81169263ebb5d2e992611e4192909116908b908b908b908b908b908b90600401612a47565b602060405180830381600087803b158015611e5b57600080fd5b505af1158015611e6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e9391906128e4565b6001600c5598975050505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b600a5473ffffffffffffffffffffffffffffffffffffffff1681565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b611f006126ec565b6006611f0a610a53565b81548110611f1457fe5b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b611f586126ec565b6006611f6383610cc5565b81548110611f6d57fe5b906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820154815250509050919050565b80820382811115610cbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612a9f565b60008115806120035750508082028282828161200057fe5b04145b610cbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612b33565b6000808211612074576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612f7a565b81838161207d57fe5b049392505050565b80820182811015610cbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612b6a565b336000908152600560205260408120906120da610cf0565b9050806120f6600354846003015461208590919063ffffffff16565b111561212e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612cb8565b8154831115612169576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612f1d565b6121736000612336565b600b546121809084611fab565b600b556003820181905581546121969084611fab565b9091555050565b600b546007546040517f70a0823100000000000000000000000000000000000000000000000000000000815260009261225592909173ffffffffffffffffffffffffffffffffffffffff909116906370a08231906121ff903090600401612979565b60206040518083038186803b15801561221757600080fd5b505afa15801561222b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224f91906128e4565b90611fab565b905060008111612291576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612ad6565b600b5461229e9082612085565b600b5573ffffffffffffffffffffffffffffffffffffffff821660009081526005602052604090206122ce610cf0565b600382015580546122df9083612085565b815560405173ffffffffffffffffffffffffffffffffffffffff8416907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c90612329908590613045565b60405180910390a2505050565b33801561237f5773ffffffffffffffffffffffffffffffffffffffff8116600090815260056020526040902061236b826104f6565b6002820155612378610a53565b6001909101555b336000908152600560205260409020600281015480156125ba5783156124035760006123a9610cf0565b9050806123c5600454856003015461208590919063ffffffff16565b11156123fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612e63565b60038301555b60006002808401829055546008546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316926370a082319261246592911690600401612979565b60206040518083038186803b15801561247d57600080fd5b505afa158015612491573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b591906128e4565b905060008282116124c657816124c8565b825b6008546002546040517fd1660f9900000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff9182169263d1660f99926125289216903390869060040161299a565b600060405180830381600087803b15801561254257600080fd5b505af1158015612556573d6000803e3d6000fd5b505060025460405133935073ffffffffffffffffffffffffffffffffffffffff90911691506000907f16dc511f817964d1eb39e0c3e84ce317f07b5b12cdfa1f8c2f179a08836af51a906125af9088908190889061305c565b60405180910390a450505b50505050565b6000808573ffffffffffffffffffffffffffffffffffffffff166323b872dd8686866040516024016125f49392919061299a565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516126429190612940565b6000604051808303816000865af19150503d806000811461267f576040519150601f19603f3d011682016040523d82523d6000602084013e612684565b606091505b50915091508180156126ae5750805115806126ae5750808060200190518101906126ae91906128ac565b6126e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612fb1565b505050505050565b60405180606001604052806000815260200160008152602001600081525090565b803573ffffffffffffffffffffffffffffffffffffffff811681146105a657600080fd5b600060208284031215612742578081fd5b61274b8261270d565b9392505050565b600080600080600080600060e0888a03121561276c578283fd5b6127758861270d565b96506127836020890161270d565b95506127916040890161270d565b945061279f6060890161270d565b93506127ad6080890161270d565b925060a0880135915060c0880135905092959891949750929550565b600080600080600080600080610100898b0312156127e5578081fd5b6127ee8961270d565b97506127fc60208a0161270d565b965061280a60408a0161270d565b9550606089013594506080890135935060a0890135925061282d60c08a0161270d565b915060e089013590509295985092959890939650565b600080600080600080600060e0888a03121561285d578283fd5b6128668861270d565b96506128746020890161270d565b955060408801359450606088013593506080880135925061289760a0890161270d565b915060c0880135905092959891949750929550565b6000602082840312156128bd578081fd5b8151801515811461274b578182fd5b6000602082840312156128dd578081fd5b5035919050565b6000602082840312156128f5578081fd5b5051919050565b6000806040838503121561290e578182fd5b50508035926020909101359150565b6000806040838503121561292f578182fd5b505080516020909101519092909150565b60008251815b818110156129605760208186018101518583015201612946565b8181111561296e5782828501525b509190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9889168152968816602088015294871660408701526060860193909352608085019190915260a084015290921660c082015260e08101919091526101000190565b73ffffffffffffffffffffffffffffffffffffffff9788168152958716602087015260408601949094526060850192909252608084015290921660a082015260c081019190915260e00190565b901515815260200190565b60208082526015908201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604082015260600190565b60208082526025908201527f5374616b65506f6f6c45706f63685265776172643a20496e76616c696420626160408201527f6c616e6365000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526014908201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604082015260600190565b60208082526014908201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604082015260600190565b60208082526026908201527f5374616b65506f6f6c45706f63685265776172643a20496e76616c696420707260408201527f6f76696465720000000000000000000000000000000000000000000000000000606082015260800190565b60208082526026908201527f5374616b65506f6f6c45706f63685265776172643a202165706f6368436f6e7460408201527f726f6c6c65720000000000000000000000000000000000000000000000000000606082015260800190565b60208082526027908201527f5374616b65506f6f6c45706f63685265776172643a2043616e6e6f7420616c6c60408201527f6f63617465203000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602e908201527f5374616b65506f6f6c45706f63685265776172643a207374696c6c20696e207760408201527f69746864726177206c6f636b7570000000000000000000000000000000000000606082015260800190565b60208082526024908201527f5374616b65506f6f6c45706f63685265776172643a20496e76616c696420736560408201527f6e64657200000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526023908201527f5f77697468647261774c6f636b757045706f6368733a206f7574206f6620726160408201527f6e67650000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5374616b65506f6f6c45706f63685265776172643a202174696d656c6f636b00604082015260600190565b60208082526031908201527f5374616b65506f6f6c45706f63685265776172643a204e6f7420616c6c6f772060408201527f656d657267656e63795769746864726177000000000000000000000000000000606082015260800190565b6020808252602c908201527f5374616b65506f6f6c45706f63685265776172643a207374696c6c20696e207260408201527f6577617264206c6f636b75700000000000000000000000000000000000000000606082015260800190565b6020808252602f908201527f5374616b65506f6f6c45706f63685265776172643a20496e697469616c697a6560408201527f206d7573742062652066616c73652e0000000000000000000000000000000000606082015260800190565b6020808252602d908201527f5374616b65506f6f6c45706f63685265776172643a20696e76616c696420776960408201527f74686472617720616d6f756e7400000000000000000000000000000000000000606082015260800190565b60208082526018908201527f64732d6d6174682d6469766973696f6e2d62792d7a65726f0000000000000000604082015260600190565b60208082526024908201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160408201527f494c454400000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601c908201527f5374616b65506f6f6c45706f63685265776172643a204c4f434b454400000000604082015260600190565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b9384526020840192909252604083015260608201526080019056fea264697066735822122015d4c8d309f093cb7799c1b70c6151c477475534f9de905011683115aec3e0c664736f6c63430007060033a2646970667358221220776c81b9054a6b3aef772f8011d2364fe31a737657f177ba9bd2050f360087d064736f6c63430007060033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100415760003560e01c806301f79fb61461004657806354fd4d501461005b578063efc81a8c14610079575b600080fd5b6100596100543660046101aa565b61008e565b005b61006361012d565b604051610070919061035c565b60405180910390f35b610081610133565b60405161007091906102c5565b86600061009d8385018561026b565b90508173ffffffffffffffffffffffffffffffffffffffff1663b33f952789878985600001518c876020015188604001516040518863ffffffff1660e01b81526004016100f0979695949392919061030c565b600060405180830381600087803b15801561010a57600080fd5b505af115801561011e573d6000803e3d6000fd5b50505050505050505050505050565b60005481565b6000803360005460405161014690610174565b6101519291906102e6565b604051809103906000f08015801561016d573d6000803e3d6000fd5b5091505090565b6132258061036683390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146101a557600080fd5b919050565b600080600080600080600060c0888a0312156101c4578283fd5b6101cd88610181565b96506101db60208901610181565b95506101e960408901610181565b94506101f760608901610181565b935061020560808901610181565b925060a088013567ffffffffffffffff80821115610221578384fd5b818a0191508a601f830112610234578384fd5b813581811115610242578485fd5b8b6020828501011115610253578485fd5b60208301945080935050505092959891949750929550565b60006060828403121561027c578081fd5b6040516060810181811067ffffffffffffffff8211171561029957fe5b6040526102a583610181565b815260208301356020820152604083013560408201528091505092915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9788168152958716602087015293861660408601529185166060850152909316608083015260a082019290925260c081019190915260e00190565b9081526020019056fe60806040526001600c55600d805460ff191690553480156200002057600080fd5b506040516200322538038062003225833981016040819052620000439162000118565b600a80546001600160a01b039093166001600160a01b031993841617905560098054909216331790915560009081556040805160608101825243815260208101838152918101838152600680546001810182559452905160039093027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f81019390935590517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40830155517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d419091015562000152565b600080604083850312156200012b578182fd5b82516001600160a01b038116811462000142578283fd5b6020939093015192949293505050565b6130c380620001626000396000f3fe608060405234801561001057600080fd5b50600436106102915760003560e01c8063714b465811610160578063d33219b4116100d8578063e9fad8ee1161008c578063efe2226611610071578063efe22266146104de578063f77c4791146104e6578063f7c618c1146104ee57610291565b8063e9fad8ee146104c3578063ebb5d2e9146104cb57610291565b8063e1f4a784116100bd578063e1f4a7841461048a578063e2dcb6161461049d578063e7d80e31146104b057610291565b8063d33219b41461047a578063db2e21bc1461048257610291565b8063b33f95271161012f578063b69ef8a811610114578063b69ef8a814610462578063b88a802f1461046a578063c5967c261461047257610291565b8063b33f95271461042e578063b56b681d1461044157610291565b8063714b4658146103f8578063900cf0cf1461040b578063a694fc3a14610413578063a8aa1b311461042657610291565b8063224556181161020e578063446a2ec8116101c257806354fd4d50116101a757806354fd4d50146103ca5780635a9c0644146103d257806362e7e463146103e557610291565b8063446a2ec8146103af5780634bf69206146103b757610291565b80632ffaaa09116101f35780632ffaaa09146103815780633468a5b8146103945780633f9e3f04146103a757610291565b806322455618146103645780632e1a7d4d1461036c57610291565b806307284ce91161026557806319262d301161024a57806319262d30146103265780631959a002146103395780631e85cd651461035c57610291565b806307284ce9146102fc57806311815a391461030457610291565b80628cc26214610296578063022ba18d146102bf57806303df4868146102c7578063046335d0146102dc575b600080fd5b6102a96102a4366004612731565b6104f6565b6040516102b69190613045565b60405180910390f35b6102a96105ab565b6102cf6105b1565b6040516102b69190612979565b6102ef6102ea366004612731565b6105cd565b6040516102b69190612a94565b6102a9610614565b6103176103123660046128cc565b6106bc565b6040516102b69392919061305c565b6102ef610334366004612731565b6106ef565b61034c610347366004612731565b61072f565b6040516102b69493929190613072565b6102a9610756565b6102a961075c565b61037f61037a3660046128cc565b6107cb565b005b61037f61038f3660046128fc565b61091f565b6102ef6103a2366004612731565b610a08565b6102a9610a53565b6102a9610a64565b61037f6103c5366004612731565b610a77565b6102a9610ba5565b61037f6103e0366004612731565b610bab565b6102a96103f3366004612731565b610c87565b6102a9610406366004612731565b610cc5565b6102a9610cf0565b61037f6104213660046128cc565b610d5b565b6102cf610e52565b61037f61043c366004612752565b610e6e565b61045461044f366004612843565b610f62565b6040516102b692919061304e565b6102a961124e565b61037f611254565b6102a9611260565b6102cf6112cb565b61037f6112e7565b6104546104983660046127c9565b6114dd565b61037f6104ab3660046128cc565b6117cc565b6102a96104be366004612731565b611b6d565b61037f611ba3565b6102a96104d9366004612843565b611bbc565b6102cf611ea4565b6102cf611ec0565b6102cf611edc565b600080610501611ef8565b604001519050600061051284611f50565b60409081015173ffffffffffffffffffffffffffffffffffffffff8616600090815260056020908152908390208351608081018552815481526001820154928101929092526002810154938201849052600301546060820152909250906105a09061059a670de0b6b3a764000061059461058c8888611fab565b865190611fe8565b90612039565b90612085565b93505050505b919050565b60045481565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60006105d7610cf0565b60045473ffffffffffffffffffffffffffffffffffffffff841660009081526005602052604090206003015461060c91612085565b111592915050565b600154604080517f07284ce9000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916307284ce9916004808301926020929190829003018186803b15801561067f57600080fd5b505afa158015610693573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b791906128e4565b905090565b600681815481106106cc57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b60006106f9610cf0565b6003805473ffffffffffffffffffffffffffffffffffffffff851660009081526005602052604090209091015461060c91612085565b60056020526000908152604090208054600182015460028301546003909301549192909184565b60035481565b6001546040517f7effa5b600000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff1690637effa5b6906107b3903090600401612979565b60206040518083038186803b15801561067f57600080fd5b600c54600114610810576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b60405180910390fd5b6000600c5561081e816120c2565b6007546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063a9059cbb9061087690339085906004016129cb565b602060405180830381600087803b15801561089057600080fd5b505af11580156108a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c891906128ac565b503373ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648260405161090f9190613045565b60405180910390a2506001600c55565b600c5460011461095b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c5560095473ffffffffffffffffffffffffffffffffffffffff1633146109b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612dcf565b8082101580156109c2575060388211155b6109f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612d72565b6003919091556004556001600c55565b60025460009073ffffffffffffffffffffffffffffffffffffffff83811691161415610a4b57610a36611ef8565b5162093a8001421015610a4b575060006105a6565b506001919050565b6006546000906106b7906001611fab565b6000610a6e611ef8565b60400151905090565b600c54600114610ab3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c55600a546040517f393a748400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063393a748490610b0e903390600401612979565b60206040518083038186803b158015610b2657600080fd5b505afa158015610b3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5e91906128ac565b610b94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612d15565b610b9d8161219d565b506001600c55565b60005481565b600c54600114610be7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c5560095473ffffffffffffffffffffffffffffffffffffffff163314610c3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612dcf565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091178155600c55565b60045473ffffffffffffffffffffffffffffffffffffffff82166000908152600560205260408120600301549091610cbf9190612085565b92915050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526005602052604090206001015490565b600154604080517f900cf0cf000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163900cf0cf916004808301926020929190829003018186803b15801561067f57600080fd5b600c54600114610d97576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c556007546040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd90610df69033903090869060040161299a565b602060405180830381600087803b158015610e1057600080fd5b505af1158015610e24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4891906128ac565b50610b9d3361219d565b60075473ffffffffffffffffffffffffffffffffffffffff1681565b600d5460ff1615610eab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612ec0565b600780547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff998a161790915560088054821697891697909717909655600980548716958816959095179094556003556004929092556001805484169185169190911781556002805490931691909316179055600d80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169091179055565b600080600c54600114610fa1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c55600a546040517f393a748400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063393a748490610ffc908c90600401612979565b60206040518083038186803b15801561101457600080fd5b505afa158015611028573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104c91906128ac565b611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612ba1565b61108b876120c2565b6007546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063095ea7b3906110e3908c908b906004016129cb565b602060405180830381600087803b1580156110fd57600080fd5b505af1158015611111573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113591906128ac565b503373ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648860405161117c9190613045565b60405180910390a26007546040517fb56b681d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81169263b56b681d926111e892909116908c908c908c908c908c908c90600401612a47565b6040805180830381600087803b15801561120157600080fd5b505af1158015611215573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611239919061291d565b6001600c55909a909950975050505050505050565b600b5481565b61125e6001612336565b565b600154604080517fc5967c26000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163c5967c26916004808301926020929190829003018186803b15801561067f57600080fd5b60095473ffffffffffffffffffffffffffffffffffffffff1681565b600c54600114611323576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c55600a546040517fea74109e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063ea74109e9061137e903090600401612979565b60206040518083038186803b15801561139657600080fd5b505afa1580156113aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ce91906128ac565b611404576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612e06565b3360009081526005602052604090208054600b546114229082611fab565b600b55600082556007546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063a9059cbb9061148190339085906004016129cb565b602060405180830381600087803b15801561149b57600080fd5b505af11580156114af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d391906128ac565b50506001600c5550565b600080600c5460011461151c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c55600a546040517f393a748400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063393a748490611577908d90600401612979565b60206040518083038186803b15801561158f57600080fd5b505afa1580156115a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c791906128ac565b6115fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612ba1565b611606876120c2565b6007546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063095ea7b39061165e908d908b906004016129cb565b602060405180830381600087803b15801561167857600080fd5b505af115801561168c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b091906128ac565b503373ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364886040516116f79190613045565b60405180910390a26007546040517fe1f4a78400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81169263e1f4a7849261176592909116908d908d908d908d908d908d908d906004016129f1565b6040805180830381600087803b15801561177e57600080fd5b505af1158015611792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b6919061291d565b6001600c55909b909a5098505050505050505050565b600c54600114611808576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c5560015473ffffffffffffffffffffffffffffffffffffffff16331461185e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612bfe565b60008111611898576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612c5b565b6002546008546040517f70a0823100000000000000000000000000000000000000000000000000000000815260009273ffffffffffffffffffffffffffffffffffffffff908116926370a08231926118f69290911690600401612979565b60206040518083038186803b15801561190e57600080fd5b505afa158015611922573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194691906128e4565b6002546008549192506119759173ffffffffffffffffffffffffffffffffffffffff91821691339116856125c0565b600b5415611b64576002546008546040517f70a0823100000000000000000000000000000000000000000000000000000000815260009273ffffffffffffffffffffffffffffffffffffffff908116926370a08231926119db9290911690600401612979565b60206040518083038186803b1580156119f357600080fd5b505afa158015611a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2b91906128e4565b9050611a378183611fab565b92506000611a43611ef8565b6040015190506000611a76611a6f600b54610594670de0b6b3a764000089611fe890919063ffffffff16565b8390612085565b9050600060405180606001604052804381526020018781526020018381525090507fae0e1452e3105698745005d16edaee897b9daf225b8434ea419008b58e60cb764387604051611ac892919061304e565b60405180910390a16006805460018101825560009190915281517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f60039092029182015560208201517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d408201556040909101517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d41909101555050505b50506001600c55565b6003805473ffffffffffffffffffffffffffffffffffffffff8316600090815260056020526040812090920154610cbf91612085565b3360009081526005602052604090205461125e906107cb565b6000600c54600114611bfa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108079061300e565b6000600c55600a546040517f393a748400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063393a748490611c55908b90600401612979565b60206040518083038186803b158015611c6d57600080fd5b505afa158015611c81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca591906128ac565b611cdb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612ba1565b611ce4866120c2565b6007546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063095ea7b390611d3c908b908a906004016129cb565b602060405180830381600087803b158015611d5657600080fd5b505af1158015611d6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8e91906128ac565b503373ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436487604051611dd59190613045565b60405180910390a26007546040517febb5d2e900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a81169263ebb5d2e992611e4192909116908b908b908b908b908b908b90600401612a47565b602060405180830381600087803b158015611e5b57600080fd5b505af1158015611e6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e9391906128e4565b6001600c5598975050505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b600a5473ffffffffffffffffffffffffffffffffffffffff1681565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b611f006126ec565b6006611f0a610a53565b81548110611f1457fe5b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b611f586126ec565b6006611f6383610cc5565b81548110611f6d57fe5b906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820154815250509050919050565b80820382811115610cbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612a9f565b60008115806120035750508082028282828161200057fe5b04145b610cbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612b33565b6000808211612074576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612f7a565b81838161207d57fe5b049392505050565b80820182811015610cbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612b6a565b336000908152600560205260408120906120da610cf0565b9050806120f6600354846003015461208590919063ffffffff16565b111561212e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612cb8565b8154831115612169576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612f1d565b6121736000612336565b600b546121809084611fab565b600b556003820181905581546121969084611fab565b9091555050565b600b546007546040517f70a0823100000000000000000000000000000000000000000000000000000000815260009261225592909173ffffffffffffffffffffffffffffffffffffffff909116906370a08231906121ff903090600401612979565b60206040518083038186803b15801561221757600080fd5b505afa15801561222b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224f91906128e4565b90611fab565b905060008111612291576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612ad6565b600b5461229e9082612085565b600b5573ffffffffffffffffffffffffffffffffffffffff821660009081526005602052604090206122ce610cf0565b600382015580546122df9083612085565b815560405173ffffffffffffffffffffffffffffffffffffffff8416907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c90612329908590613045565b60405180910390a2505050565b33801561237f5773ffffffffffffffffffffffffffffffffffffffff8116600090815260056020526040902061236b826104f6565b6002820155612378610a53565b6001909101555b336000908152600560205260409020600281015480156125ba5783156124035760006123a9610cf0565b9050806123c5600454856003015461208590919063ffffffff16565b11156123fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612e63565b60038301555b60006002808401829055546008546040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316926370a082319261246592911690600401612979565b60206040518083038186803b15801561247d57600080fd5b505afa158015612491573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b591906128e4565b905060008282116124c657816124c8565b825b6008546002546040517fd1660f9900000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff9182169263d1660f99926125289216903390869060040161299a565b600060405180830381600087803b15801561254257600080fd5b505af1158015612556573d6000803e3d6000fd5b505060025460405133935073ffffffffffffffffffffffffffffffffffffffff90911691506000907f16dc511f817964d1eb39e0c3e84ce317f07b5b12cdfa1f8c2f179a08836af51a906125af9088908190889061305c565b60405180910390a450505b50505050565b6000808573ffffffffffffffffffffffffffffffffffffffff166323b872dd8686866040516024016125f49392919061299a565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516126429190612940565b6000604051808303816000865af19150503d806000811461267f576040519150601f19603f3d011682016040523d82523d6000602084013e612684565b606091505b50915091508180156126ae5750805115806126ae5750808060200190518101906126ae91906128ac565b6126e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080790612fb1565b505050505050565b60405180606001604052806000815260200160008152602001600081525090565b803573ffffffffffffffffffffffffffffffffffffffff811681146105a657600080fd5b600060208284031215612742578081fd5b61274b8261270d565b9392505050565b600080600080600080600060e0888a03121561276c578283fd5b6127758861270d565b96506127836020890161270d565b95506127916040890161270d565b945061279f6060890161270d565b93506127ad6080890161270d565b925060a0880135915060c0880135905092959891949750929550565b600080600080600080600080610100898b0312156127e5578081fd5b6127ee8961270d565b97506127fc60208a0161270d565b965061280a60408a0161270d565b9550606089013594506080890135935060a0890135925061282d60c08a0161270d565b915060e089013590509295985092959890939650565b600080600080600080600060e0888a03121561285d578283fd5b6128668861270d565b96506128746020890161270d565b955060408801359450606088013593506080880135925061289760a0890161270d565b915060c0880135905092959891949750929550565b6000602082840312156128bd578081fd5b8151801515811461274b578182fd5b6000602082840312156128dd578081fd5b5035919050565b6000602082840312156128f5578081fd5b5051919050565b6000806040838503121561290e578182fd5b50508035926020909101359150565b6000806040838503121561292f578182fd5b505080516020909101519092909150565b60008251815b818110156129605760208186018101518583015201612946565b8181111561296e5782828501525b509190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9889168152968816602088015294871660408701526060860193909352608085019190915260a084015290921660c082015260e08101919091526101000190565b73ffffffffffffffffffffffffffffffffffffffff9788168152958716602087015260408601949094526060850192909252608084015290921660a082015260c081019190915260e00190565b901515815260200190565b60208082526015908201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604082015260600190565b60208082526025908201527f5374616b65506f6f6c45706f63685265776172643a20496e76616c696420626160408201527f6c616e6365000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526014908201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604082015260600190565b60208082526014908201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604082015260600190565b60208082526026908201527f5374616b65506f6f6c45706f63685265776172643a20496e76616c696420707260408201527f6f76696465720000000000000000000000000000000000000000000000000000606082015260800190565b60208082526026908201527f5374616b65506f6f6c45706f63685265776172643a202165706f6368436f6e7460408201527f726f6c6c65720000000000000000000000000000000000000000000000000000606082015260800190565b60208082526027908201527f5374616b65506f6f6c45706f63685265776172643a2043616e6e6f7420616c6c60408201527f6f63617465203000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602e908201527f5374616b65506f6f6c45706f63685265776172643a207374696c6c20696e207760408201527f69746864726177206c6f636b7570000000000000000000000000000000000000606082015260800190565b60208082526024908201527f5374616b65506f6f6c45706f63685265776172643a20496e76616c696420736560408201527f6e64657200000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526023908201527f5f77697468647261774c6f636b757045706f6368733a206f7574206f6620726160408201527f6e67650000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5374616b65506f6f6c45706f63685265776172643a202174696d656c6f636b00604082015260600190565b60208082526031908201527f5374616b65506f6f6c45706f63685265776172643a204e6f7420616c6c6f772060408201527f656d657267656e63795769746864726177000000000000000000000000000000606082015260800190565b6020808252602c908201527f5374616b65506f6f6c45706f63685265776172643a207374696c6c20696e207260408201527f6577617264206c6f636b75700000000000000000000000000000000000000000606082015260800190565b6020808252602f908201527f5374616b65506f6f6c45706f63685265776172643a20496e697469616c697a6560408201527f206d7573742062652066616c73652e0000000000000000000000000000000000606082015260800190565b6020808252602d908201527f5374616b65506f6f6c45706f63685265776172643a20696e76616c696420776960408201527f74686472617720616d6f756e7400000000000000000000000000000000000000606082015260800190565b60208082526018908201527f64732d6d6174682d6469766973696f6e2d62792d7a65726f0000000000000000604082015260600190565b60208082526024908201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160408201527f494c454400000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601c908201527f5374616b65506f6f6c45706f63685265776172643a204c4f434b454400000000604082015260600190565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b9384526020840192909252604083015260608201526080019056fea264697066735822122015d4c8d309f093cb7799c1b70c6151c477475534f9de905011683115aec3e0c664736f6c63430007060033a2646970667358221220776c81b9054a6b3aef772f8011d2364fe31a737657f177ba9bd2050f360087d064736f6c63430007060033

Deployed Bytecode Sourcemap

41939:1135:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42382:689;;;;;;:::i;:::-;;:::i;:::-;;42004:38;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;42197:177;;;:::i;:::-;;;;;;;:::i;42382:689::-;42665:11;42616:25;42729:34;;;;42740:4;42729:34;:::i;:::-;42690:73;;42774:4;:15;;;42804:4;42831:19;42874:8;42898:14;:30;;;42943:11;42969:14;:35;;;43019:14;:33;;;42774:289;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42382:689;;;;;;;;;:::o;42004:38::-;;;;:::o;42197:177::-;42242:7;42262:25;42315:10;42327:7;;42290:45;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42262:73:0;-1:-1:-1;;42197:177:0;:::o;-1:-1:-1:-;;;;;;;;:::o;14:198:1:-;84:20;;144:42;133:54;;123:65;;113:2;;202:1;199;192:12;113:2;65:147;;;:::o;217:1024::-;;;;;;;;433:3;421:9;412:7;408:23;404:33;401:2;;;455:6;447;440:22;401:2;483:31;504:9;483:31;:::i;:::-;473:41;;533:40;569:2;558:9;554:18;533:40;:::i;:::-;523:50;;592:40;628:2;617:9;613:18;592:40;:::i;:::-;582:50;;651:40;687:2;676:9;672:18;651:40;:::i;:::-;641:50;;710:41;746:3;735:9;731:19;710:41;:::i;:::-;700:51;;802:3;791:9;787:19;774:33;826:18;867:2;859:6;856:14;853:2;;;888:6;880;873:22;853:2;931:6;920:9;916:22;906:32;;976:7;969:4;965:2;961:13;957:27;947:2;;1003:6;995;988:22;947:2;1048;1035:16;1074:2;1066:6;1063:14;1060:2;;;1095:6;1087;1080:22;1060:2;1145:7;1140:2;1131:6;1127:2;1123:15;1119:24;1116:37;1113:2;;;1171:6;1163;1156:22;1113:2;1207;1203;1199:11;1189:21;;1229:6;1219:16;;;;;391:850;;;;;;;;;;:::o;1246:586::-;;1390:2;1378:9;1369:7;1365:23;1361:32;1358:2;;;1411:6;1403;1396:22;1358:2;1449;1443:9;1491:2;1483:6;1479:15;1560:6;1548:10;1545:22;1524:18;1512:10;1509:34;1506:62;1503:2;;;1571:9;1503:2;1598;1591:22;1637:31;1658:9;1637:31;:::i;:::-;1629:6;1622:47;1730:2;1719:9;1715:18;1702:32;1697:2;1689:6;1685:15;1678:57;1796:2;1785:9;1781:18;1768:32;1763:2;1755:6;1751:15;1744:57;1820:6;1810:16;;;1348:484;;;;:::o;1837:226::-;2013:42;2001:55;;;;1983:74;;1971:2;1956:18;;1938:125::o;2068:305::-;2280:42;2268:55;;;;2250:74;;2355:2;2340:18;;2333:34;2238:2;2223:18;;2205:168::o;2378:713::-;2703:42;2772:15;;;2754:34;;2824:15;;;2819:2;2804:18;;2797:43;2876:15;;;2871:2;2856:18;;2849:43;2928:15;;;2923:2;2908:18;;2901:43;2981:15;;;2975:3;2960:19;;2953:44;3028:3;3013:19;;3006:35;;;;3072:3;3057:19;;3050:35;;;;2680:3;2665:19;;2647:444::o;3096:177::-;3242:25;;;3230:2;3215:18;;3197:76::o

Swarm Source

ipfs://776c81b9054a6b3aef772f8011d2364fe31a737657f177ba9bd2050f360087d0

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ 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.