Contract Address Details

0x206949295503c4FC5C9757099db479dD5383A5dC

Contract Name
MultiPools
Creator
0x1e9d5f–779a29 at 0x98b21d–5b6fb4
Balance
0 Doge
Tokens
Fetching tokens...
Transactions
26,565 Transactions
Transfers
27,919 Transfers
Gas Used
2,452,062,249
Last Balance Update
2857488
Contract name:
MultiPools




Optimization enabled
false
Compiler version
v0.8.16+commit.07a7930e




EVM Version
default




Verified at
2022-08-23T04:15:00.043236Z

Contract source code

// SPDX-License-Identifier: RYOSHI
pragma solidity ^0.8.0;

// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

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

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

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

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

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

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

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

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

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

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

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

// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

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

contract MultiPools is Ownable, ReentrancyGuard, Pausable {
    /* ========== STATE VARIABLES ========== */

    struct Pool {
        address stakingToken;
        address rewardsToken;
        // Duration of rewards to be paid out (in seconds)
        uint256 duration;
        // Timestamp of when the rewards finish
        uint256 finishAt;
        // Minimum of last updated time and reward finish time
        uint256 updatedAt;
        // Reward to be paid out per second
        uint256 rewardRate;
        // Sum of (reward rate * dt * 1e18 / total supply)
        uint256 rewardPerTokenStored;
        // Total staked
        uint256 totalSupply;
    }

    uint256 public poolCounter = 0;
    // Index => pool info
    mapping(uint256 => Pool) public pools;
    // User address => rewardPerTokenStored
    mapping(uint256 => mapping(address => uint256))
        public userRewardPerTokenPaid;
    // User address => rewards to be claimed
    mapping(uint256 => mapping(address => uint256)) public rewards;
    // User address => staked amount
    mapping(uint256 => mapping(address => uint256)) public balanceOf;

    /* ========== VIEWS ========== */

    function lastTimeRewardApplicable(uint256 _poolId)
        public
        view
        returns (uint256)
    {
        Pool storage pool = pools[_poolId];
        return
            block.timestamp < pool.finishAt ? block.timestamp : pool.finishAt;
    }

    function rewardPerToken(uint256 _poolId) public view returns (uint256) {
        Pool storage pool = pools[_poolId];

        if (pool.totalSupply == 0) {
            return pool.rewardPerTokenStored;
        }

        return
            pool.rewardPerTokenStored +
            (pool.rewardRate *
                (lastTimeRewardApplicable(_poolId) - pool.updatedAt) *
                1e18) /
            pool.totalSupply;
    }

    function earned(uint256 _poolId, address _account)
        public
        view
        returns (uint256)
    {
        return
            ((balanceOf[_poolId][_account] *
                (rewardPerToken(_poolId) -
                    userRewardPerTokenPaid[_poolId][_account])) / 1e18) +
            rewards[_poolId][_account];
    }

    function getRewardForDuration(uint256 _poolId)
        external
        view
        returns (uint256)
    {
        Pool storage pool = pools[_poolId];
        return pool.rewardRate * pool.duration;
    }

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

    function createPool(address _stakingToken, address _rewardsToken)
        public
        onlyOwner
    {
        poolCounter++;
        Pool storage pool = pools[poolCounter];
        pool.stakingToken = _stakingToken;
        pool.rewardsToken = _rewardsToken;
        emit PoolCreated(poolCounter, _stakingToken, _rewardsToken);
    }

    function stake(uint256 _poolId, uint256 _amount)
        external
        nonReentrant
        whenNotPaused
        updateReward(_poolId, msg.sender)
    {
        require(_amount > 0, "Cannot stake 0");
        Pool storage pool = pools[_poolId];
        pool.totalSupply = pool.totalSupply + _amount;
        balanceOf[_poolId][msg.sender] =
            balanceOf[_poolId][msg.sender] +
            _amount;
        IERC20((pool.stakingToken)).transferFrom(
            msg.sender,
            address(this),
            _amount
        );
        emit Staked(_poolId, msg.sender, _amount);
    }

    function withdraw(uint256 _poolId, uint256 _amount)
        public
        nonReentrant
        updateReward(_poolId, msg.sender)
    {
        require(_amount > 0, "Cannot withdraw 0");
        Pool storage pool = pools[_poolId];
        pool.totalSupply = pool.totalSupply - _amount;
        balanceOf[_poolId][msg.sender] =
            balanceOf[_poolId][msg.sender] -
            _amount;
        IERC20(pool.stakingToken).transfer(msg.sender, _amount);
        emit Withdrawn(_poolId, msg.sender, _amount);
    }

    function getReward(uint256 _poolId)
        public
        nonReentrant
        updateReward(_poolId, msg.sender)
    {
        Pool storage pool = pools[_poolId];
        uint256 reward = rewards[_poolId][msg.sender];
        if (reward > 0) {
            rewards[_poolId][msg.sender] = 0;
            IERC20(pool.rewardsToken).transfer(msg.sender, reward);
            emit RewardPaid(_poolId, msg.sender, reward);
        }
    }

    function exit(uint256 _poolId) external {
        withdraw(_poolId, balanceOf[_poolId][msg.sender]);
        getReward(_poolId);
    }

    /* ========== RESTRICTED FUNCTIONS ========== */

    function notifyRewardAmount(uint256 _poolId, uint256 _reward)
        external
        onlyOwner
        updateReward(_poolId, address(0))
    {
        Pool storage pool = pools[_poolId];

        if (block.timestamp >= pool.finishAt) {
            pool.rewardRate = _reward / pool.duration;
        } else {
            uint256 remaining = pool.finishAt - block.timestamp;
            uint256 leftover = remaining * pool.rewardRate;
            pool.rewardRate = (_reward + leftover) / pool.duration;
        }

        // Ensure the provided reward amount is not more than the balance in the contract.
        // This keeps the reward rate in the right range, preventing overflows due to
        // very high values of rewardRate in the earned and rewardsPerToken functions;
        // Reward + leftover must be less than 2^256 / 10^18 to avoid overflow.
        uint256 balance = IERC20(pool.rewardsToken).balanceOf(address(this));
        require(
            pool.rewardRate <= balance / pool.duration,
            "Provided reward too high"
        );

        pool.updatedAt = block.timestamp;
        pool.finishAt = block.timestamp + pool.duration;
        emit RewardAdded(_poolId, _reward);
    }

    // Added to support recovering LP Rewards from other systems such as BAL to be distributed to holders
    function recoverERC20(
        uint256 _poolId,
        address _tokenAddress,
        uint256 _tokenAmount
    ) external onlyOwner {
        Pool storage pool = pools[_poolId];
        require(
            _tokenAddress != address(pool.stakingToken),
            "Cannot withdraw the staking token"
        );
        IERC20(_tokenAddress).transfer(owner(), _tokenAmount);
        emit Recovered(_poolId, _tokenAddress, _tokenAmount);
    }

    function setRewardsDuration(uint256 _poolId, uint256 _rewardsDuration)
        external
        onlyOwner
    {
        Pool storage pool = pools[_poolId];

        require(
            block.timestamp > pool.finishAt,
            "Previous rewards period must be complete before changing the duration for the new period"
        );
        pool.duration = _rewardsDuration;
        emit RewardsDurationUpdated(_poolId, pool.duration);
    }

    /* ========== MODIFIERS ========== */

    modifier updateReward(uint256 _poolId, address _account) {
        Pool storage pool = pools[_poolId];
        pool.rewardPerTokenStored = rewardPerToken(_poolId);
        pool.updatedAt = lastTimeRewardApplicable(_poolId);
        if (_account != address(0)) {
            rewards[_poolId][_account] = earned(_poolId, _account);
            userRewardPerTokenPaid[_poolId][_account] = pool
                .rewardPerTokenStored;
        }
        _;
    }

    /* ========== EVENTS ========== */

    event PoolCreated(
        uint256 indexed poolId,
        address stakingToken,
        address rewardsToken
    );
    event RewardAdded(uint256 indexed poolId, uint256 reward);
    event Staked(uint256 indexed poolId, address indexed user, uint256 amount);
    event Withdrawn(
        uint256 indexed poolId,
        address indexed user,
        uint256 amount
    );
    event RewardPaid(
        uint256 indexed poolId,
        address indexed user,
        uint256 reward
    );
    event RewardsDurationUpdated(uint256 indexed poolId, uint256 newDuration);
    event Recovered(uint256 indexed poolId, address token, uint256 amount);
}
        

Contract ABI

[{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"PoolCreated","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256","indexed":true},{"type":"address","name":"stakingToken","internalType":"address","indexed":false},{"type":"address","name":"rewardsToken","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Recovered","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RewardAdded","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256","indexed":true},{"type":"uint256","name":"reward","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RewardPaid","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"reward","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RewardsDurationUpdated","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256","indexed":true},{"type":"uint256","name":"newDuration","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Staked","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Withdrawn","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createPool","inputs":[{"type":"address","name":"_stakingToken","internalType":"address"},{"type":"address","name":"_rewardsToken","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"earned","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"},{"type":"address","name":"_account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"exit","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"getReward","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getRewardForDuration","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastTimeRewardApplicable","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"notifyRewardAmount","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"},{"type":"uint256","name":"_reward","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"paused","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"poolCounter","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"stakingToken","internalType":"address"},{"type":"address","name":"rewardsToken","internalType":"address"},{"type":"uint256","name":"duration","internalType":"uint256"},{"type":"uint256","name":"finishAt","internalType":"uint256"},{"type":"uint256","name":"updatedAt","internalType":"uint256"},{"type":"uint256","name":"rewardRate","internalType":"uint256"},{"type":"uint256","name":"rewardPerTokenStored","internalType":"uint256"},{"type":"uint256","name":"totalSupply","internalType":"uint256"}],"name":"pools","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"recoverERC20","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"},{"type":"address","name":"_tokenAddress","internalType":"address"},{"type":"uint256","name":"_tokenAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewardPerToken","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewards","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRewardsDuration","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"},{"type":"uint256","name":"_rewardsDuration","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stake","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"userRewardPerTokenPaid","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[{"type":"uint256","name":"_poolId","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]}]
            

Contract Creation Code

0x608060405260006003553480156200001657600080fd5b50620000376200002b6200005f60201b60201c565b6200006760201b60201c565b600180819055506000600260006101000a81548160ff0219169083151502179055506200012b565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6124db806200013b6000396000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c8063874c120b116100b8578063ac4afa381161007c578063ac4afa3814610323578063e34336151461035a578063e39c08fc14610376578063eeca1562146103a6578063f2db11af146103d6578063f2fde38b1461040657610136565b8063874c120b1461027f5780638ca43f91146102af5780638da5cb5b146102cb5780639e3079cb146102e95780639efb70371461030757610136565b8063441a3e70116100ff578063441a3e70146102035780635c975abb1461021f578063715018a61461023d5780637b0472f0146102475780637f8661a11461026357610136565b8062a47ddd1461013b5780630e213a3d1461016b5780631c4b774b1461019b578063246132f9146101b75780633656eec2146101d3575b600080fd5b61015560048036038101906101509190611afe565b610422565b6040516101629190611b4d565b60405180910390f35b61018560048036038101906101809190611b68565b610447565b6040516101929190611b4d565b60405180910390f35b6101b560048036038101906101b09190611b68565b61047b565b005b6101d160048036038101906101cc9190611b95565b610778565b005b6101ed60048036038101906101e89190611afe565b610a8e565b6040516101fa9190611b4d565b60405180910390f35b61021d60048036038101906102189190611b95565b610ab3565b005b610227610e06565b6040516102349190611bf0565b60405180910390f35b610245610e1d565b005b610261600480360381019061025c9190611b95565b610e31565b005b61027d60048036038101906102789190611b68565b61118e565b005b61029960048036038101906102949190611b68565b6111f4565b6040516102a69190611b4d565b60405180910390f35b6102c960048036038101906102c49190611c0b565b611286565b005b6102d36113fd565b6040516102e09190611c6d565b60405180910390f35b6102f1611426565b6040516102fe9190611b4d565b60405180910390f35b610321600480360381019061031c9190611b95565b61142c565b005b61033d60048036038101906103389190611b68565b6114db565b604051610351989796959493929190611c88565b60405180910390f35b610374600480360381019061036f9190611d06565b611563565b005b610390600480360381019061038b9190611afe565b611663565b60405161039d9190611b4d565b60405180910390f35b6103c060048036038101906103bb9190611b68565b61179a565b6040516103cd9190611b4d565b60405180910390f35b6103f060048036038101906103eb9190611afe565b6117d1565b6040516103fd9190611b4d565b60405180910390f35b610420600480360381019061041b9190611d46565b6117f6565b005b6005602052816000526040600020602052806000526040600020600091509150505481565b600080600460008481526020019081526020016000209050806002015481600501546104739190611da2565b915050919050565b610483611879565b803360006004600084815260200190815260200160002090506104a5836111f4565b81600601819055506104b68361179a565b8160040181905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146105aa576104fc8383611663565b6006600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600601546005600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b600060046000868152602001908152602001600020905060006006600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008111156107685760006006600088815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b81526004016106d4929190611dfc565b6020604051808303816000875af11580156106f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107179190611e51565b503373ffffffffffffffffffffffffffffffffffffffff16867f04492fab062412e7e4e5f46c9e919f1640652946a5e163ad6e6c1c03d87954d28360405161075f9190611b4d565b60405180910390a35b50505050506107756118c8565b50565b6107806118d1565b816000806004600084815260200190815260200160002090506107a2836111f4565b81600601819055506107b38361179a565b8160040181905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146108a7576107f98383611663565b6006600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600601546005600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b6000600460008781526020019081526020016000209050806003015442106108e6578060020154856108d99190611ead565b8160050181905550610934565b60004282600301546108f89190611ede565b9050600082600501548261090c9190611da2565b90508260020154818861091f9190611f12565b6109299190611ead565b836005018190555050505b60008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109939190611c6d565b602060405180830381865afa1580156109b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d49190611f5b565b90508160020154816109e69190611ead565b82600501541115610a2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a2390611fe5565b60405180910390fd5b428260040181905550816002015442610a459190611f12565b8260030181905550867f6c07ee05dcf262f13abf9d87b846ee789d2f90fe991d495acd7d7fc109ee1f5587604051610a7d9190611b4d565b60405180910390a250505050505050565b6007602052816000526040600020602052806000526040600020600091509150505481565b610abb611879565b81336000600460008481526020019081526020016000209050610add836111f4565b8160060181905550610aee8361179a565b8160040181905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610be257610b348383611663565b6006600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600601546005600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b60008411610c25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1c90612051565b60405180910390fd5b6000600460008781526020019081526020016000209050848160070154610c4c9190611ede565b8160070181905550846007600088815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610cb09190611ede565b6007600088815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33876040518363ffffffff1660e01b8152600401610d63929190611dfc565b6020604051808303816000875af1158015610d82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da69190611e51565b503373ffffffffffffffffffffffffffffffffffffffff16867fcf7d23a3cbe4e8b36ff82fd1b05b1b17373dc7804b4ebbd6e2356716ef20237287604051610dee9190611b4d565b60405180910390a350505050610e026118c8565b5050565b6000600260009054906101000a900460ff16905090565b610e256118d1565b610e2f600061194f565b565b610e39611879565b610e41611a13565b81336000600460008481526020019081526020016000209050610e63836111f4565b8160060181905550610e748361179a565b8160040181905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610f6857610eba8383611663565b6006600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600601546005600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b60008411610fab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fa2906120bd565b60405180910390fd5b6000600460008781526020019081526020016000209050848160070154610fd29190611f12565b8160070181905550846007600088815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546110369190611f12565b6007600088815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b81526004016110eb939291906120dd565b6020604051808303816000875af115801561110a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112e9190611e51565b503373ffffffffffffffffffffffffffffffffffffffff16867f18dcd430020e4d4899772fd94a8b40451dc5044dfb70bc46b532eeae431c864f876040516111769190611b4d565b60405180910390a35050505061118a6118c8565b5050565b6111e8816007600084815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610ab3565b6111f18161047b565b50565b6000806004600084815260200190815260200160002090506000816007015403611225578060060154915050611281565b8060070154670de0b6b3a764000082600401546112418661179a565b61124b9190611ede565b836005015461125a9190611da2565b6112649190611da2565b61126e9190611ead565b816006015461127d9190611f12565b9150505b919050565b61128e6118d1565b60006004600085815260200190815260200160002090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611337576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132e90612186565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61135b6113fd565b846040518363ffffffff1660e01b8152600401611379929190611dfc565b6020604051808303816000875af1158015611398573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bc9190611e51565b50837f986159ceffdc791f0b3a91a14e4141b9e6f9b1cf6130751c819dd646f616b81084846040516113ef929190611dfc565b60405180910390a250505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60035481565b6114346118d1565b600060046000848152602001908152602001600020905080600301544211611491576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114889061223e565b60405180910390fd5b818160020181905550827fd20a04eb2807bde8cbdf16ef27a46d94a3162d81818f1781c0fe4ed9194ca39182600201546040516114ce9190611b4d565b60405180910390a2505050565b60046020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154908060030154908060040154908060050154908060060154908060070154905088565b61156b6118d1565b6003600081548092919061157e9061225e565b919050555060006004600060035481526020019081526020016000209050828160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506003547f1a7a1d16c3ec9167827a7be3534be26288720a0bdd3de56d290f415db3d3e0a684846040516116569291906122a6565b60405180910390a2505050565b60006006600084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054670de0b6b3a76400006005600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611719866111f4565b6117239190611ede565b6007600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461177e9190611da2565b6117889190611ead565b6117929190611f12565b905092915050565b600080600460008481526020019081526020016000209050806003015442106117c75780600301546117c9565b425b915050919050565b6006602052816000526040600020602052806000526040600020600091509150505481565b6117fe6118d1565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361186d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161186490612341565b60405180910390fd5b6118768161194f565b50565b6002600154036118be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118b5906123ad565b60405180910390fd5b6002600181905550565b60018081905550565b6118d9611a5d565b73ffffffffffffffffffffffffffffffffffffffff166118f76113fd565b73ffffffffffffffffffffffffffffffffffffffff161461194d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161194490612419565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b611a1b610e06565b15611a5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a5290612485565b60405180910390fd5b565b600033905090565b600080fd5b6000819050919050565b611a7d81611a6a565b8114611a8857600080fd5b50565b600081359050611a9a81611a74565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611acb82611aa0565b9050919050565b611adb81611ac0565b8114611ae657600080fd5b50565b600081359050611af881611ad2565b92915050565b60008060408385031215611b1557611b14611a65565b5b6000611b2385828601611a8b565b9250506020611b3485828601611ae9565b9150509250929050565b611b4781611a6a565b82525050565b6000602082019050611b626000830184611b3e565b92915050565b600060208284031215611b7e57611b7d611a65565b5b6000611b8c84828501611a8b565b91505092915050565b60008060408385031215611bac57611bab611a65565b5b6000611bba85828601611a8b565b9250506020611bcb85828601611a8b565b9150509250929050565b60008115159050919050565b611bea81611bd5565b82525050565b6000602082019050611c056000830184611be1565b92915050565b600080600060608486031215611c2457611c23611a65565b5b6000611c3286828701611a8b565b9350506020611c4386828701611ae9565b9250506040611c5486828701611a8b565b9150509250925092565b611c6781611ac0565b82525050565b6000602082019050611c826000830184611c5e565b92915050565b600061010082019050611c9e600083018b611c5e565b611cab602083018a611c5e565b611cb86040830189611b3e565b611cc56060830188611b3e565b611cd26080830187611b3e565b611cdf60a0830186611b3e565b611cec60c0830185611b3e565b611cf960e0830184611b3e565b9998505050505050505050565b60008060408385031215611d1d57611d1c611a65565b5b6000611d2b85828601611ae9565b9250506020611d3c85828601611ae9565b9150509250929050565b600060208284031215611d5c57611d5b611a65565b5b6000611d6a84828501611ae9565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611dad82611a6a565b9150611db883611a6a565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611df157611df0611d73565b5b828202905092915050565b6000604082019050611e116000830185611c5e565b611e1e6020830184611b3e565b9392505050565b611e2e81611bd5565b8114611e3957600080fd5b50565b600081519050611e4b81611e25565b92915050565b600060208284031215611e6757611e66611a65565b5b6000611e7584828501611e3c565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611eb882611a6a565b9150611ec383611a6a565b925082611ed357611ed2611e7e565b5b828204905092915050565b6000611ee982611a6a565b9150611ef483611a6a565b9250828203905081811115611f0c57611f0b611d73565b5b92915050565b6000611f1d82611a6a565b9150611f2883611a6a565b9250828201905080821115611f4057611f3f611d73565b5b92915050565b600081519050611f5581611a74565b92915050565b600060208284031215611f7157611f70611a65565b5b6000611f7f84828501611f46565b91505092915050565b600082825260208201905092915050565b7f50726f76696465642072657761726420746f6f20686967680000000000000000600082015250565b6000611fcf601883611f88565b9150611fda82611f99565b602082019050919050565b60006020820190508181036000830152611ffe81611fc2565b9050919050565b7f43616e6e6f742077697468647261772030000000000000000000000000000000600082015250565b600061203b601183611f88565b915061204682612005565b602082019050919050565b6000602082019050818103600083015261206a8161202e565b9050919050565b7f43616e6e6f74207374616b652030000000000000000000000000000000000000600082015250565b60006120a7600e83611f88565b91506120b282612071565b602082019050919050565b600060208201905081810360008301526120d68161209a565b9050919050565b60006060820190506120f26000830186611c5e565b6120ff6020830185611c5e565b61210c6040830184611b3e565b949350505050565b7f43616e6e6f7420776974686472617720746865207374616b696e6720746f6b6560008201527f6e00000000000000000000000000000000000000000000000000000000000000602082015250565b6000612170602183611f88565b915061217b82612114565b604082019050919050565b6000602082019050818103600083015261219f81612163565b9050919050565b7f50726576696f7573207265776172647320706572696f64206d7573742062652060008201527f636f6d706c657465206265666f7265206368616e67696e67207468652064757260208201527f6174696f6e20666f7220746865206e657720706572696f640000000000000000604082015250565b6000612228605883611f88565b9150612233826121a6565b606082019050919050565b600060208201905081810360008301526122578161221b565b9050919050565b600061226982611a6a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361229b5761229a611d73565b5b600182019050919050565b60006040820190506122bb6000830185611c5e565b6122c86020830184611c5e565b9392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061232b602683611f88565b9150612336826122cf565b604082019050919050565b6000602082019050818103600083015261235a8161231e565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000612397601f83611f88565b91506123a282612361565b602082019050919050565b600060208201905081810360008301526123c68161238a565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000612403602083611f88565b915061240e826123cd565b602082019050919050565b60006020820190508181036000830152612432816123f6565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b600061246f601083611f88565b915061247a82612439565b602082019050919050565b6000602082019050818103600083015261249e81612462565b905091905056fea264697066735822122079eecfcac730e6c0140814361f99e0e866919857497d33cd0ba323f2df65fd2f64736f6c63430008100033

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106101365760003560e01c8063874c120b116100b8578063ac4afa381161007c578063ac4afa3814610323578063e34336151461035a578063e39c08fc14610376578063eeca1562146103a6578063f2db11af146103d6578063f2fde38b1461040657610136565b8063874c120b1461027f5780638ca43f91146102af5780638da5cb5b146102cb5780639e3079cb146102e95780639efb70371461030757610136565b8063441a3e70116100ff578063441a3e70146102035780635c975abb1461021f578063715018a61461023d5780637b0472f0146102475780637f8661a11461026357610136565b8062a47ddd1461013b5780630e213a3d1461016b5780631c4b774b1461019b578063246132f9146101b75780633656eec2146101d3575b600080fd5b61015560048036038101906101509190611afe565b610422565b6040516101629190611b4d565b60405180910390f35b61018560048036038101906101809190611b68565b610447565b6040516101929190611b4d565b60405180910390f35b6101b560048036038101906101b09190611b68565b61047b565b005b6101d160048036038101906101cc9190611b95565b610778565b005b6101ed60048036038101906101e89190611afe565b610a8e565b6040516101fa9190611b4d565b60405180910390f35b61021d60048036038101906102189190611b95565b610ab3565b005b610227610e06565b6040516102349190611bf0565b60405180910390f35b610245610e1d565b005b610261600480360381019061025c9190611b95565b610e31565b005b61027d60048036038101906102789190611b68565b61118e565b005b61029960048036038101906102949190611b68565b6111f4565b6040516102a69190611b4d565b60405180910390f35b6102c960048036038101906102c49190611c0b565b611286565b005b6102d36113fd565b6040516102e09190611c6d565b60405180910390f35b6102f1611426565b6040516102fe9190611b4d565b60405180910390f35b610321600480360381019061031c9190611b95565b61142c565b005b61033d60048036038101906103389190611b68565b6114db565b604051610351989796959493929190611c88565b60405180910390f35b610374600480360381019061036f9190611d06565b611563565b005b610390600480360381019061038b9190611afe565b611663565b60405161039d9190611b4d565b60405180910390f35b6103c060048036038101906103bb9190611b68565b61179a565b6040516103cd9190611b4d565b60405180910390f35b6103f060048036038101906103eb9190611afe565b6117d1565b6040516103fd9190611b4d565b60405180910390f35b610420600480360381019061041b9190611d46565b6117f6565b005b6005602052816000526040600020602052806000526040600020600091509150505481565b600080600460008481526020019081526020016000209050806002015481600501546104739190611da2565b915050919050565b610483611879565b803360006004600084815260200190815260200160002090506104a5836111f4565b81600601819055506104b68361179a565b8160040181905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146105aa576104fc8383611663565b6006600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600601546005600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b600060046000868152602001908152602001600020905060006006600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008111156107685760006006600088815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b81526004016106d4929190611dfc565b6020604051808303816000875af11580156106f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107179190611e51565b503373ffffffffffffffffffffffffffffffffffffffff16867f04492fab062412e7e4e5f46c9e919f1640652946a5e163ad6e6c1c03d87954d28360405161075f9190611b4d565b60405180910390a35b50505050506107756118c8565b50565b6107806118d1565b816000806004600084815260200190815260200160002090506107a2836111f4565b81600601819055506107b38361179a565b8160040181905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146108a7576107f98383611663565b6006600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600601546005600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b6000600460008781526020019081526020016000209050806003015442106108e6578060020154856108d99190611ead565b8160050181905550610934565b60004282600301546108f89190611ede565b9050600082600501548261090c9190611da2565b90508260020154818861091f9190611f12565b6109299190611ead565b836005018190555050505b60008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109939190611c6d565b602060405180830381865afa1580156109b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d49190611f5b565b90508160020154816109e69190611ead565b82600501541115610a2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a2390611fe5565b60405180910390fd5b428260040181905550816002015442610a459190611f12565b8260030181905550867f6c07ee05dcf262f13abf9d87b846ee789d2f90fe991d495acd7d7fc109ee1f5587604051610a7d9190611b4d565b60405180910390a250505050505050565b6007602052816000526040600020602052806000526040600020600091509150505481565b610abb611879565b81336000600460008481526020019081526020016000209050610add836111f4565b8160060181905550610aee8361179a565b8160040181905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610be257610b348383611663565b6006600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600601546005600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b60008411610c25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1c90612051565b60405180910390fd5b6000600460008781526020019081526020016000209050848160070154610c4c9190611ede565b8160070181905550846007600088815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610cb09190611ede565b6007600088815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33876040518363ffffffff1660e01b8152600401610d63929190611dfc565b6020604051808303816000875af1158015610d82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da69190611e51565b503373ffffffffffffffffffffffffffffffffffffffff16867fcf7d23a3cbe4e8b36ff82fd1b05b1b17373dc7804b4ebbd6e2356716ef20237287604051610dee9190611b4d565b60405180910390a350505050610e026118c8565b5050565b6000600260009054906101000a900460ff16905090565b610e256118d1565b610e2f600061194f565b565b610e39611879565b610e41611a13565b81336000600460008481526020019081526020016000209050610e63836111f4565b8160060181905550610e748361179a565b8160040181905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610f6857610eba8383611663565b6006600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600601546005600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b60008411610fab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fa2906120bd565b60405180910390fd5b6000600460008781526020019081526020016000209050848160070154610fd29190611f12565b8160070181905550846007600088815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546110369190611f12565b6007600088815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b81526004016110eb939291906120dd565b6020604051808303816000875af115801561110a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112e9190611e51565b503373ffffffffffffffffffffffffffffffffffffffff16867f18dcd430020e4d4899772fd94a8b40451dc5044dfb70bc46b532eeae431c864f876040516111769190611b4d565b60405180910390a35050505061118a6118c8565b5050565b6111e8816007600084815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610ab3565b6111f18161047b565b50565b6000806004600084815260200190815260200160002090506000816007015403611225578060060154915050611281565b8060070154670de0b6b3a764000082600401546112418661179a565b61124b9190611ede565b836005015461125a9190611da2565b6112649190611da2565b61126e9190611ead565b816006015461127d9190611f12565b9150505b919050565b61128e6118d1565b60006004600085815260200190815260200160002090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611337576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132e90612186565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61135b6113fd565b846040518363ffffffff1660e01b8152600401611379929190611dfc565b6020604051808303816000875af1158015611398573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bc9190611e51565b50837f986159ceffdc791f0b3a91a14e4141b9e6f9b1cf6130751c819dd646f616b81084846040516113ef929190611dfc565b60405180910390a250505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60035481565b6114346118d1565b600060046000848152602001908152602001600020905080600301544211611491576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114889061223e565b60405180910390fd5b818160020181905550827fd20a04eb2807bde8cbdf16ef27a46d94a3162d81818f1781c0fe4ed9194ca39182600201546040516114ce9190611b4d565b60405180910390a2505050565b60046020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154908060030154908060040154908060050154908060060154908060070154905088565b61156b6118d1565b6003600081548092919061157e9061225e565b919050555060006004600060035481526020019081526020016000209050828160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506003547f1a7a1d16c3ec9167827a7be3534be26288720a0bdd3de56d290f415db3d3e0a684846040516116569291906122a6565b60405180910390a2505050565b60006006600084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054670de0b6b3a76400006005600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611719866111f4565b6117239190611ede565b6007600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461177e9190611da2565b6117889190611ead565b6117929190611f12565b905092915050565b600080600460008481526020019081526020016000209050806003015442106117c75780600301546117c9565b425b915050919050565b6006602052816000526040600020602052806000526040600020600091509150505481565b6117fe6118d1565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361186d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161186490612341565b60405180910390fd5b6118768161194f565b50565b6002600154036118be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118b5906123ad565b60405180910390fd5b6002600181905550565b60018081905550565b6118d9611a5d565b73ffffffffffffffffffffffffffffffffffffffff166118f76113fd565b73ffffffffffffffffffffffffffffffffffffffff161461194d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161194490612419565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b611a1b610e06565b15611a5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a5290612485565b60405180910390fd5b565b600033905090565b600080fd5b6000819050919050565b611a7d81611a6a565b8114611a8857600080fd5b50565b600081359050611a9a81611a74565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611acb82611aa0565b9050919050565b611adb81611ac0565b8114611ae657600080fd5b50565b600081359050611af881611ad2565b92915050565b60008060408385031215611b1557611b14611a65565b5b6000611b2385828601611a8b565b9250506020611b3485828601611ae9565b9150509250929050565b611b4781611a6a565b82525050565b6000602082019050611b626000830184611b3e565b92915050565b600060208284031215611b7e57611b7d611a65565b5b6000611b8c84828501611a8b565b91505092915050565b60008060408385031215611bac57611bab611a65565b5b6000611bba85828601611a8b565b9250506020611bcb85828601611a8b565b9150509250929050565b60008115159050919050565b611bea81611bd5565b82525050565b6000602082019050611c056000830184611be1565b92915050565b600080600060608486031215611c2457611c23611a65565b5b6000611c3286828701611a8b565b9350506020611c4386828701611ae9565b9250506040611c5486828701611a8b565b9150509250925092565b611c6781611ac0565b82525050565b6000602082019050611c826000830184611c5e565b92915050565b600061010082019050611c9e600083018b611c5e565b611cab602083018a611c5e565b611cb86040830189611b3e565b611cc56060830188611b3e565b611cd26080830187611b3e565b611cdf60a0830186611b3e565b611cec60c0830185611b3e565b611cf960e0830184611b3e565b9998505050505050505050565b60008060408385031215611d1d57611d1c611a65565b5b6000611d2b85828601611ae9565b9250506020611d3c85828601611ae9565b9150509250929050565b600060208284031215611d5c57611d5b611a65565b5b6000611d6a84828501611ae9565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611dad82611a6a565b9150611db883611a6a565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611df157611df0611d73565b5b828202905092915050565b6000604082019050611e116000830185611c5e565b611e1e6020830184611b3e565b9392505050565b611e2e81611bd5565b8114611e3957600080fd5b50565b600081519050611e4b81611e25565b92915050565b600060208284031215611e6757611e66611a65565b5b6000611e7584828501611e3c565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611eb882611a6a565b9150611ec383611a6a565b925082611ed357611ed2611e7e565b5b828204905092915050565b6000611ee982611a6a565b9150611ef483611a6a565b9250828203905081811115611f0c57611f0b611d73565b5b92915050565b6000611f1d82611a6a565b9150611f2883611a6a565b9250828201905080821115611f4057611f3f611d73565b5b92915050565b600081519050611f5581611a74565b92915050565b600060208284031215611f7157611f70611a65565b5b6000611f7f84828501611f46565b91505092915050565b600082825260208201905092915050565b7f50726f76696465642072657761726420746f6f20686967680000000000000000600082015250565b6000611fcf601883611f88565b9150611fda82611f99565b602082019050919050565b60006020820190508181036000830152611ffe81611fc2565b9050919050565b7f43616e6e6f742077697468647261772030000000000000000000000000000000600082015250565b600061203b601183611f88565b915061204682612005565b602082019050919050565b6000602082019050818103600083015261206a8161202e565b9050919050565b7f43616e6e6f74207374616b652030000000000000000000000000000000000000600082015250565b60006120a7600e83611f88565b91506120b282612071565b602082019050919050565b600060208201905081810360008301526120d68161209a565b9050919050565b60006060820190506120f26000830186611c5e565b6120ff6020830185611c5e565b61210c6040830184611b3e565b949350505050565b7f43616e6e6f7420776974686472617720746865207374616b696e6720746f6b6560008201527f6e00000000000000000000000000000000000000000000000000000000000000602082015250565b6000612170602183611f88565b915061217b82612114565b604082019050919050565b6000602082019050818103600083015261219f81612163565b9050919050565b7f50726576696f7573207265776172647320706572696f64206d7573742062652060008201527f636f6d706c657465206265666f7265206368616e67696e67207468652064757260208201527f6174696f6e20666f7220746865206e657720706572696f640000000000000000604082015250565b6000612228605883611f88565b9150612233826121a6565b606082019050919050565b600060208201905081810360008301526122578161221b565b9050919050565b600061226982611a6a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361229b5761229a611d73565b5b600182019050919050565b60006040820190506122bb6000830185611c5e565b6122c86020830184611c5e565b9392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061232b602683611f88565b9150612336826122cf565b604082019050919050565b6000602082019050818103600083015261235a8161231e565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000612397601f83611f88565b91506123a282612361565b602082019050919050565b600060208201905081810360008301526123c68161238a565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000612403602083611f88565b915061240e826123cd565b602082019050919050565b60006020820190508181036000830152612432816123f6565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b600061246f601083611f88565b915061247a82612439565b602082019050919050565b6000602082019050818103600083015261249e81612462565b905091905056fea264697066735822122079eecfcac730e6c0140814361f99e0e866919857497d33cd0ba323f2df65fd2f64736f6c63430008100033