false
true
0

Contract Address Details

0xa5255A4E00d4e2762EA7e9e1Dc4Ecf68b981e760

Contract Name
XusdGenesisRewardPool
Creator
0x000006–a90503 at 0x2e6729–fcc486
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
9,201 Transactions
Transfers
0 Transfers
Gas Used
0
Last Balance Update
25929643
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
XusdGenesisRewardPool




Optimization enabled
false
Compiler version
v0.8.26+commit.8a97fa7a




EVM Version
paris




Verified at
2024-10-01T21:26:42.811035Z

Constructor Arguments

0x000000000000000000000000bbea78397d4d4590882efcc4820f03074ab2ab2900000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066f2fa4200000000000000000000000000000000000000000073ce27351811f40c0000000000000000000000000000000000000000000000000000000000000000e6b6800000000000000000000000000000000000000000000000000000000000000000

Arg [0] (address) : 0xbbea78397d4d4590882efcc4820f03074ab2ab29
Arg [1] (address[]) : []
Arg [2] (uint256) : 0
Arg [3] (uint256) : 1727199810
Arg [4] (uint256) : 140000000000000000000000000
Arg [5] (uint256) : 15120000

              

contracts/staking.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

contract XusdGenesisRewardPool {
    using EnumerableSet for EnumerableSet.AddressSet;

    struct UserInfo {
        uint256 amount;
        uint256 rewardDebt;
    }

    struct PoolInfo {
        IERC20 token;
        uint256 allocPoint;
        uint256 lastRewardTime;
        uint256 accXusdPerShare;
        bool isStarted;
        uint256 maxDeposit;
    }

    EnumerableSet.AddressSet private _comissionTokens;
    uint256 public comissionPercent;

    address public operator;
    IERC20 public Xusd;
    PoolInfo[] public poolInfo;
    mapping(uint256 => mapping(address => UserInfo)) public userInfo;
    uint256 public totalAllocPoint = 0;
    uint256 public poolStartTime;
    uint256 public poolEndTime;

    uint256 public XusdPerSecond;
    uint256 public runningTime;
    uint256 public totalRewards;

    event Deposit(address indexed user, uint256 indexed pid, uint256 amount);
    event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);
    event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount);
    event RewardPaid(address indexed user, uint256 amount);

    constructor(
        address _Xusd,
        address[] memory comissionTokens_,
        uint256 _comissionPercent,
        uint256 _poolStartTime,
        uint256 _totalRewards,
        uint256 _runningTime
    ) {
        require(block.timestamp < _poolStartTime, "late");
        require(_Xusd != address(0), "XusdGenesisPool: Xusd is zero address");
        require(_totalRewards > 0, "XusdGenesisPool: totalRewards is zero");
        require(_runningTime > 0, "XusdGenesisPool: runningTime is zero");
        Xusd = IERC20(_Xusd);
        totalRewards = _totalRewards;
        runningTime = _runningTime;
        XusdPerSecond = totalRewards / runningTime;
        for (uint256 i = 0; i < comissionTokens_.length; i++) {
            _comissionTokens.add(comissionTokens_[i]);
        }
        comissionPercent = _comissionPercent;
        poolStartTime = _poolStartTime;
        poolEndTime = poolStartTime + runningTime;
        operator = msg.sender;
    }

    function comissionTokensCount() external view returns (uint256) {
        return _comissionTokens.length();
    }

    function comissionToken(uint256 index) external view returns (address) {
        return _comissionTokens.at(index);
    }

    function pendingXusd(uint256 _pid, address _user) external view returns (uint256) {
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][_user];
        uint256 accXusdPerShare = pool.accXusdPerShare;
        uint256 tokenSupply = pool.token.balanceOf(address(this));
        if (block.timestamp > pool.lastRewardTime && tokenSupply != 0) {
            uint256 _generatedReward = getGeneratedReward(pool.lastRewardTime, block.timestamp);
            uint256 _XusdReward = (_generatedReward * pool.allocPoint) / totalAllocPoint;
            accXusdPerShare += (_XusdReward * 1e18) / tokenSupply;
        }
        return (user.amount * accXusdPerShare) / 1e18 - user.rewardDebt;
    }

    function getGeneratedReward(uint256 _fromTime, uint256 _toTime) public view returns (uint256) {
        if (_fromTime >= _toTime) return 0;
        if (_toTime >= poolEndTime) {
            if (_fromTime >= poolEndTime) return 0;
            if (_fromTime <= poolStartTime) return (poolEndTime - poolStartTime) * XusdPerSecond;
            return (poolEndTime - _fromTime) * XusdPerSecond;
        } else {
            if (_toTime <= poolStartTime) return 0;
            if (_fromTime <= poolStartTime) return (_toTime - poolStartTime) * XusdPerSecond;
            return (_toTime - _fromTime) * XusdPerSecond;
        }
    }

    function checkPoolDuplicate(IERC20 _token) internal view {
        uint256 length = poolInfo.length;
        for (uint256 pid = 0; pid < length; ++pid) {
            require(poolInfo[pid].token != _token, "XusdGenesisPool: existing pool?");
        }
    }

    function add(
        uint256 _allocPoint,
        IERC20 _token,
        bool _withUpdate,
        uint256 _lastRewardTime,
        uint256 _maxDeposit
    ) external onlyOperator {
        checkPoolDuplicate(_token);
        if (_withUpdate) {
            massUpdatePools();
        }
        if (block.timestamp < poolStartTime) {
            if (_lastRewardTime == 0) {
                _lastRewardTime = poolStartTime;
            } else if (_lastRewardTime < poolStartTime) {
                _lastRewardTime = poolStartTime;
            }
        } else {
            if (_lastRewardTime == 0 || _lastRewardTime < block.timestamp) {
                _lastRewardTime = block.timestamp;
            }
        }
        bool _isStarted = (_lastRewardTime <= poolStartTime) || (_lastRewardTime <= block.timestamp);
        poolInfo.push(
            PoolInfo({
                token: _token,
                allocPoint: _allocPoint,
                lastRewardTime: _lastRewardTime,
                accXusdPerShare: 0,
                isStarted: _isStarted,
                maxDeposit: _maxDeposit
            })
        );
        if (_isStarted) {
            totalAllocPoint += _allocPoint;
        }
    }

    function deposit(uint256 _pid, uint256 _amount) external {
        address _sender = msg.sender;
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][_sender];
        updatePool(_pid);
        if (user.amount > 0) {
            uint256 _pending = (user.amount * pool.accXusdPerShare) / 1e18 - user.rewardDebt;
            if (_pending > 0) {
                safeXusdTransfer(_sender, _pending);
                emit RewardPaid(_sender, _pending);
            }
        }
        uint256 possibleToDeposit = pool.maxDeposit - user.amount;
        uint256 amount = _amount > possibleToDeposit ? possibleToDeposit : _amount;
        if (amount > 0) {
            pool.token.transferFrom(_sender, address(this), amount);
            if (_comissionTokens.contains(address(pool.token))) {
                uint256 hundred = 10000;
                user.amount += (amount * (hundred - comissionPercent)) / hundred;
            } else {
                user.amount += amount;
            }
        }
        user.rewardDebt = (user.amount * pool.accXusdPerShare) / 1e18;
        emit Deposit(_sender, _pid, amount);
    }

    function emergencyWithdraw(uint256 _pid) external {
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][msg.sender];
        uint256 _amount = user.amount;
        user.amount = 0;
        user.rewardDebt = 0;
        pool.token.transfer(msg.sender, _amount);
        emit EmergencyWithdraw(msg.sender, _pid, _amount);
    }

    function governanceRecoverUnsupported(IERC20 _token, uint256 amount, address to) external onlyOperator {
        if (block.timestamp < poolEndTime + 30 days) {
            require(_token != Xusd, "Xusd");
            uint256 length = poolInfo.length;
            for (uint256 pid = 0; pid < length; ++pid) {
                PoolInfo storage pool = poolInfo[pid];
                require(_token != pool.token, "pool.token");
            }
        }
        _token.transfer(to, amount);
    }

    function set(uint256 _pid, uint256 _allocPoint) external onlyOperator {
        massUpdatePools();
        PoolInfo storage pool = poolInfo[_pid];
        if (pool.isStarted) {
            totalAllocPoint = totalAllocPoint - pool.allocPoint + _allocPoint;
        }
        pool.allocPoint = _allocPoint;
    }

    function setOperator(address _operator) external onlyOperator {
        operator = _operator;
    }

    function withdraw(uint256 _pid, uint256 _amount) external {
        address _sender = msg.sender;
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][_sender];
        require(user.amount >= _amount, "withdraw: not good");
        updatePool(_pid);
        uint256 _pending = (user.amount * pool.accXusdPerShare) / 1e18 - user.rewardDebt;
        if (_pending > 0) {
            safeXusdTransfer(_sender, _pending);
            emit RewardPaid(_sender, _pending);
        }
        if (_amount > 0) {
            user.amount -= _amount;
            pool.token.transfer(_sender, _amount);
        }
        user.rewardDebt = (user.amount * pool.accXusdPerShare) / 1e18;
        emit Withdraw(_sender, _pid, _amount);
    }

    function massUpdatePools() public {
        uint256 length = poolInfo.length;
        for (uint256 pid = 0; pid < length; ++pid) {
            updatePool(pid);
        }
    }

    function updatePool(uint256 _pid) public {
        PoolInfo storage pool = poolInfo[_pid];
        if (block.timestamp <= pool.lastRewardTime) {
            return;
        }
        uint256 tokenSupply = pool.token.balanceOf(address(this));
        if (tokenSupply == 0) {
            pool.lastRewardTime = block.timestamp;
            return;
        }
        if (!pool.isStarted) {
            pool.isStarted = true;
            totalAllocPoint += pool.allocPoint;
        }
        if (totalAllocPoint > 0) {
            uint256 _generatedReward = getGeneratedReward(pool.lastRewardTime, block.timestamp);
            uint256 _XusdReward = (_generatedReward * pool.allocPoint) / totalAllocPoint;
            pool.accXusdPerShare += (_XusdReward * 1e18) / tokenSupply;
        }
        pool.lastRewardTime = block.timestamp;
    }

    function safeXusdTransfer(address _to, uint256 _amount) internal {
        uint256 _XusdBalance = Xusd.balanceOf(address(this));
        if (_XusdBalance > 0) {
            if (_amount > _XusdBalance) {
                Xusd.transfer(_to, _XusdBalance);
            } else {
                Xusd.transfer(_to, _amount);
            }
        }
    }

    modifier onlyOperator() {
        require(operator == msg.sender, "XusdGenesisPool: caller is not the operator");
        _;
    }
}
        

@openzeppelin/contracts/interfaces/draft-IERC6093.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
          

@openzeppelin/contracts/token/ERC20/ERC20.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

    mapping(address account => mapping(address spender => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     * ```
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}
          

@openzeppelin/contracts/token/ERC20/IERC20.sol

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

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}
          

@openzeppelin/contracts/utils/Context.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

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

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

@openzeppelin/contracts/utils/structs/EnumerableSet.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position is the index of the value in the `values` array plus 1.
        // Position 0 is used to mean a value is not in the set.
        mapping(bytes32 value => uint256) _positions;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._positions[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We cache the value's position to prevent multiple reads from the same storage slot
        uint256 position = set._positions[value];

        if (position != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 valueIndex = position - 1;
            uint256 lastIndex = set._values.length - 1;

            if (valueIndex != lastIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the lastValue to the index where the value to delete is
                set._values[valueIndex] = lastValue;
                // Update the tracked position of the lastValue (that was just moved)
                set._positions[lastValue] = position;
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the tracked position for the deleted slot
            delete set._positions[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._positions[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}
          

Compiler Settings

{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata","storageLayout"],"":["ast"]}},"optimizer":{"runs":200,"enabled":false},"libraries":{},"evmVersion":"paris"}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_Xusd","internalType":"address"},{"type":"address[]","name":"comissionTokens_","internalType":"address[]"},{"type":"uint256","name":"_comissionPercent","internalType":"uint256"},{"type":"uint256","name":"_poolStartTime","internalType":"uint256"},{"type":"uint256","name":"_totalRewards","internalType":"uint256"},{"type":"uint256","name":"_runningTime","internalType":"uint256"}]},{"type":"event","name":"Deposit","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"pid","internalType":"uint256","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"EmergencyWithdraw","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"pid","internalType":"uint256","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RewardPaid","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Withdraw","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"pid","internalType":"uint256","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"Xusd","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"XusdPerSecond","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"add","inputs":[{"type":"uint256","name":"_allocPoint","internalType":"uint256"},{"type":"address","name":"_token","internalType":"contract IERC20"},{"type":"bool","name":"_withUpdate","internalType":"bool"},{"type":"uint256","name":"_lastRewardTime","internalType":"uint256"},{"type":"uint256","name":"_maxDeposit","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"comissionPercent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"comissionToken","inputs":[{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"comissionTokensCount","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deposit","inputs":[{"type":"uint256","name":"_pid","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"emergencyWithdraw","inputs":[{"type":"uint256","name":"_pid","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getGeneratedReward","inputs":[{"type":"uint256","name":"_fromTime","internalType":"uint256"},{"type":"uint256","name":"_toTime","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"governanceRecoverUnsupported","inputs":[{"type":"address","name":"_token","internalType":"contract IERC20"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"massUpdatePools","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"operator","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pendingXusd","inputs":[{"type":"uint256","name":"_pid","internalType":"uint256"},{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"poolEndTime","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"token","internalType":"contract IERC20"},{"type":"uint256","name":"allocPoint","internalType":"uint256"},{"type":"uint256","name":"lastRewardTime","internalType":"uint256"},{"type":"uint256","name":"accXusdPerShare","internalType":"uint256"},{"type":"bool","name":"isStarted","internalType":"bool"},{"type":"uint256","name":"maxDeposit","internalType":"uint256"}],"name":"poolInfo","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"poolStartTime","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"runningTime","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"set","inputs":[{"type":"uint256","name":"_pid","internalType":"uint256"},{"type":"uint256","name":"_allocPoint","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setOperator","inputs":[{"type":"address","name":"_operator","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalAllocPoint","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalRewards","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updatePool","inputs":[{"type":"uint256","name":"_pid","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"rewardDebt","internalType":"uint256"}],"name":"userInfo","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[{"type":"uint256","name":"_pid","internalType":"uint256"},{"type":"uint256","name":"_amount","internalType":"uint256"}]}]
              

Contract Creation Code

0x6080604052600060075534801561001557600080fd5b50604051612e4e380380612e4e8339818101604052810190610037919061055c565b824210610079576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161007090610662565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16036100e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100df906106f4565b60405180910390fd5b6000821161012b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161012290610786565b60405180910390fd5b6000811161016e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161016590610818565b60405180910390fd5b85600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600c8190555080600b81905550600b54600c546101cd9190610896565b600a8190555060005b855181101561021b5761020d8682815181106101f5576101f46108c7565b5b6020026020010151600061028c60201b90919060201c565b5080806001019150506101d6565b508360028190555082600881905550600b5460085461023a91906108f6565b60098190555033600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050505061092a565b60006102ba836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6102c260201b60201c565b905092915050565b60006102d4838361033860201b60201c565b61032d578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050610332565b600090505b92915050565b600080836001016000848152602001908152602001600020541415905092915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061039a8261036f565b9050919050565b6103aa8161038f565b81146103b557600080fd5b50565b6000815190506103c7816103a1565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61041b826103d2565b810181811067ffffffffffffffff8211171561043a576104396103e3565b5b80604052505050565b600061044d61035b565b90506104598282610412565b919050565b600067ffffffffffffffff821115610479576104786103e3565b5b602082029050602081019050919050565b600080fd5b60006104a261049d8461045e565b610443565b905080838252602082019050602084028301858111156104c5576104c461048a565b5b835b818110156104ee57806104da88826103b8565b8452602084019350506020810190506104c7565b5050509392505050565b600082601f83011261050d5761050c6103cd565b5b815161051d84826020860161048f565b91505092915050565b6000819050919050565b61053981610526565b811461054457600080fd5b50565b60008151905061055681610530565b92915050565b60008060008060008060c0878903121561057957610578610365565b5b600061058789828a016103b8565b965050602087015167ffffffffffffffff8111156105a8576105a761036a565b5b6105b489828a016104f8565b95505060406105c589828a01610547565b94505060606105d689828a01610547565b93505060806105e789828a01610547565b92505060a06105f889828a01610547565b9150509295509295509295565b600082825260208201905092915050565b7f6c61746500000000000000000000000000000000000000000000000000000000600082015250565b600061064c600483610605565b915061065782610616565b602082019050919050565b6000602082019050818103600083015261067b8161063f565b9050919050565b7f5875736447656e65736973506f6f6c3a2058757364206973207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b60006106de602583610605565b91506106e982610682565b604082019050919050565b6000602082019050818103600083015261070d816106d1565b9050919050565b7f5875736447656e65736973506f6f6c3a20746f74616c5265776172647320697360008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b6000610770602583610605565b915061077b82610714565b604082019050919050565b6000602082019050818103600083015261079f81610763565b9050919050565b7f5875736447656e65736973506f6f6c3a2072756e6e696e6754696d652069732060008201527f7a65726f00000000000000000000000000000000000000000000000000000000602082015250565b6000610802602483610605565b915061080d826107a6565b604082019050919050565b60006020820190508181036000830152610831816107f5565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006108a182610526565b91506108ac83610526565b9250826108bc576108bb610838565b5b828204905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061090182610526565b915061090c83610526565b925082820190508082111561092457610923610867565b5b92915050565b612515806109396000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c80635f96dc11116100c357806392fae48d1161007c57806392fae48d146103a657806393f1a40b146103c4578063943f013d146103f5578063b3ab15fb14610413578063e2bbb1581461042f578063f25bb8651461044b57610158565b80635f96dc11146102f6578063628b409f1461031457806362e006c714610332578063630b5ba11461034e5780636e271dd5146103585780637805583c1461037657610158565b806351eb05a61161011557806351eb05a6146102365780635312ea8e1461025257806354575af41461026e578063570ca7351461028a5780635715f8f9146102a85780635b142956146102c657610158565b80630e15561a1461015d5780631526fe271461017b57806317caf6f1146101b05780631ab06ee5146101ce578063231f0c6a146101ea578063441a3e701461021a575b600080fd5b610165610469565b6040516101729190611c3b565b60405180910390f35b61019560048036038101906101909190611c87565b61046f565b6040516101a796959493929190611d4e565b60405180910390f35b6101b86104e8565b6040516101c59190611c3b565b60405180910390f35b6101e860048036038101906101e39190611daf565b6104ee565b005b61020460048036038101906101ff9190611daf565b6105f5565b6040516102119190611c3b565b60405180910390f35b610234600480360381019061022f9190611daf565b6106d0565b005b610250600480360381019061024b9190611c87565b610989565b005b61026c60048036038101906102679190611c87565b610b54565b005b61028860048036038101906102839190611e6b565b610ce3565b005b610292610f7b565b60405161029f9190611ecd565b60405180910390f35b6102b0610fa1565b6040516102bd9190611c3b565b60405180910390f35b6102e060048036038101906102db9190611c87565b610fa7565b6040516102ed9190611ecd565b60405180910390f35b6102fe610fc4565b60405161030b9190611c3b565b60405180910390f35b61031c610fca565b6040516103299190611c3b565b60405180910390f35b61034c60048036038101906103479190611f14565b610fd0565b005b610356611201565b005b61036061122e565b60405161036d9190611c3b565b60405180910390f35b610390600480360381019061038b9190611f8f565b611234565b60405161039d9190611c3b565b60405180910390f35b6103ae611413565b6040516103bb9190611c3b565b60405180910390f35b6103de60048036038101906103d99190611f8f565b611424565b6040516103ec929190611fcf565b60405180910390f35b6103fd611455565b60405161040a9190611c3b565b60405180910390f35b61042d60048036038101906104289190611ff8565b61145b565b005b61044960048036038101906104449190611daf565b61152f565b005b610453611867565b6040516104609190612025565b60405180910390f35b600c5481565b6005818154811061047f57600080fd5b90600052602060002090600602016000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020154908060030154908060040160009054906101000a900460ff16908060050154905086565b60075481565b3373ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461057e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610575906120c3565b60405180910390fd5b610586611201565b60006005838154811061059c5761059b6120e3565b5b906000526020600020906006020190508060040160009054906101000a900460ff16156105e7578181600101546007546105d69190612141565b6105e09190612175565b6007819055505b818160010181905550505050565b600081831061060757600090506106ca565b600954821061067157600954831061062257600090506106ca565b600854831161064f57600a5460085460095461063e9190612141565b61064891906121a9565b90506106ca565b600a54836009546106609190612141565b61066a91906121a9565b90506106ca565b600854821161068357600090506106ca565b60085483116106ae57600a546008548361069d9190612141565b6106a791906121a9565b90506106ca565b600a5483836106bd9190612141565b6106c791906121a9565b90505b92915050565b60003390506000600584815481106106eb576106ea6120e3565b5b9060005260206000209060060201905060006006600086815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508381600001541015610796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161078d90612237565b60405180910390fd5b61079f85610989565b60008160010154670de0b6b3a7640000846003015484600001546107c391906121a9565b6107cd9190612286565b6107d79190612141565b9050600081111561083b576107ec848261188d565b8373ffffffffffffffffffffffffffffffffffffffff167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486826040516108329190611c3b565b60405180910390a25b600085111561090357848260000160008282546108589190612141565b925050819055508260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85876040518363ffffffff1660e01b81526004016108be9291906122b7565b6020604051808303816000875af11580156108dd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090191906122f5565b505b670de0b6b3a76400008360030154836000015461092091906121a9565b61092a9190612286565b8260010181905550858473ffffffffffffffffffffffffffffffffffffffff167ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568876040516109799190611c3b565b60405180910390a3505050505050565b60006005828154811061099f5761099e6120e3565b5b90600052602060002090600602019050806002015442116109c05750610b51565b60008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610a1f9190611ecd565b602060405180830381865afa158015610a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a609190612337565b905060008103610a7a574282600201819055505050610b51565b8160040160009054906101000a900460ff16610acb5760018260040160006101000a81548160ff021916908315150217905550816001015460076000828254610ac39190612175565b925050819055505b60006007541115610b45576000610ae68360020154426105f5565b90506000600754846001015483610afd91906121a9565b610b079190612286565b905082670de0b6b3a764000082610b1e91906121a9565b610b289190612286565b846003016000828254610b3b9190612175565b9250508190555050505b42826002018190555050505b50565b600060058281548110610b6a57610b696120e3565b5b9060005260206000209060060201905060006006600084815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154905060008260000181905550600082600101819055508260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401610c4a9291906122b7565b6020604051808303816000875af1158015610c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8d91906122f5565b50833373ffffffffffffffffffffffffffffffffffffffff167fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae059583604051610cd59190611c3b565b60405180910390a350505050565b3373ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610d73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d6a906120c3565b60405180910390fd5b62278d00600954610d849190612175565b421015610ef757600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e12906123b0565b60405180910390fd5b6000600580549050905060005b81811015610ef457600060058281548110610e4657610e456120e3565b5b906000526020600020906006020190508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603610ee8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610edf9061241c565b60405180910390fd5b50806001019050610e28565b50505b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb82846040518363ffffffff1660e01b8152600401610f329291906122b7565b6020604051808303816000875af1158015610f51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7591906122f5565b50505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60025481565b6000610fbd826000611a8c90919063ffffffff16565b9050919050565b60085481565b600a5481565b3373ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611060576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611057906120c3565b60405180910390fd5b61106984611aa6565b821561107857611077611201565b5b6008544210156110aa57600082036110945760085491506110a5565b6008548210156110a45760085491505b5b6110c2565b60008214806110b857504282105b156110c1574291505b5b6000600854831115806110d55750428311155b905060056040518060c001604052808773ffffffffffffffffffffffffffffffffffffffff16815260200188815260200185815260200160008152602001831515815260200184815250908060018154018082558091505060019003906000526020600020906006020160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155604082015181600201556060820151816003015560808201518160040160006101000a81548160ff02191690831515021790555060a08201518160050155505080156111f95785600760008282546111f19190612175565b925050819055505b505050505050565b6000600580549050905060005b8181101561122a5761121f81610989565b80600101905061120e565b5050565b60095481565b6000806005848154811061124b5761124a6120e3565b5b9060005260206000209060060201905060006006600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008260030154905060008360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016113179190611ecd565b602060405180830381865afa158015611334573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113589190612337565b905083600201544211801561136e575060008114155b156113d55760006113838560020154426105f5565b9050600060075486600101548361139a91906121a9565b6113a49190612286565b905082670de0b6b3a7640000826113bb91906121a9565b6113c59190612286565b846113d09190612175565b935050505b8260010154670de0b6b3a76400008385600001546113f391906121a9565b6113fd9190612286565b6114079190612141565b94505050505092915050565b600061141f6000611b7e565b905090565b6006602052816000526040600020602052806000526040600020600091509150508060000154908060010154905082565b600b5481565b3373ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e2906120c3565b60405180910390fd5b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600033905060006005848154811061154a576115496120e3565b5b9060005260206000209060060201905060006006600086815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506115b785610989565b6000816000015411156116625760008160010154670de0b6b3a7640000846003015484600001546115e891906121a9565b6115f29190612286565b6115fc9190612141565b9050600081111561166057611611848261188d565b8373ffffffffffffffffffffffffffffffffffffffff167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486826040516116579190611c3b565b60405180910390a25b505b6000816000015483600501546116789190612141565b90506000818611611689578561168b565b815b905060008111156117e0578360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd8630846040518463ffffffff1660e01b81526004016116f79392919061243c565b6020604051808303816000875af1158015611716573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173a91906122f5565b506117738460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000611b9390919063ffffffff16565b156117c35760006127109050806002548261178e9190612141565b8361179991906121a9565b6117a39190612286565b8460000160008282546117b69190612175565b92505081905550506117df565b808360000160008282546117d79190612175565b925050819055505b5b670de0b6b3a7640000846003015484600001546117fd91906121a9565b6118079190612286565b8360010181905550868573ffffffffffffffffffffffffffffffffffffffff167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15836040516118569190611c3b565b60405180910390a350505050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016118ea9190611ecd565b602060405180830381865afa158015611907573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061192b9190612337565b90506000811115611a8757808211156119e457600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84836040518363ffffffff1660e01b815260040161199b9291906122b7565b6020604051808303816000875af11580156119ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119de91906122f5565b50611a86565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401611a419291906122b7565b6020604051808303816000875af1158015611a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8491906122f5565b505b5b505050565b6000611a9b8360000183611bc3565b60001c905092915050565b6000600580549050905060005b81811015611b79578273ffffffffffffffffffffffffffffffffffffffff1660058281548110611ae657611ae56120e3565b5b906000526020600020906006020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603611b6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b65906124bf565b60405180910390fd5b806001019050611ab3565b505050565b6000611b8c82600001611bee565b9050919050565b6000611bbb836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611bff565b905092915050565b6000826000018281548110611bdb57611bda6120e3565b5b9060005260206000200154905092915050565b600081600001805490509050919050565b600080836001016000848152602001908152602001600020541415905092915050565b6000819050919050565b611c3581611c22565b82525050565b6000602082019050611c506000830184611c2c565b92915050565b600080fd5b611c6481611c22565b8114611c6f57600080fd5b50565b600081359050611c8181611c5b565b92915050565b600060208284031215611c9d57611c9c611c56565b5b6000611cab84828501611c72565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000611cf9611cf4611cef84611cb4565b611cd4565b611cb4565b9050919050565b6000611d0b82611cde565b9050919050565b6000611d1d82611d00565b9050919050565b611d2d81611d12565b82525050565b60008115159050919050565b611d4881611d33565b82525050565b600060c082019050611d636000830189611d24565b611d706020830188611c2c565b611d7d6040830187611c2c565b611d8a6060830186611c2c565b611d976080830185611d3f565b611da460a0830184611c2c565b979650505050505050565b60008060408385031215611dc657611dc5611c56565b5b6000611dd485828601611c72565b9250506020611de585828601611c72565b9150509250929050565b6000611dfa82611cb4565b9050919050565b6000611e0c82611def565b9050919050565b611e1c81611e01565b8114611e2757600080fd5b50565b600081359050611e3981611e13565b92915050565b611e4881611def565b8114611e5357600080fd5b50565b600081359050611e6581611e3f565b92915050565b600080600060608486031215611e8457611e83611c56565b5b6000611e9286828701611e2a565b9350506020611ea386828701611c72565b9250506040611eb486828701611e56565b9150509250925092565b611ec781611def565b82525050565b6000602082019050611ee26000830184611ebe565b92915050565b611ef181611d33565b8114611efc57600080fd5b50565b600081359050611f0e81611ee8565b92915050565b600080600080600060a08688031215611f3057611f2f611c56565b5b6000611f3e88828901611c72565b9550506020611f4f88828901611e2a565b9450506040611f6088828901611eff565b9350506060611f7188828901611c72565b9250506080611f8288828901611c72565b9150509295509295909350565b60008060408385031215611fa657611fa5611c56565b5b6000611fb485828601611c72565b9250506020611fc585828601611e56565b9150509250929050565b6000604082019050611fe46000830185611c2c565b611ff16020830184611c2c565b9392505050565b60006020828403121561200e5761200d611c56565b5b600061201c84828501611e56565b91505092915050565b600060208201905061203a6000830184611d24565b92915050565b600082825260208201905092915050565b7f5875736447656e65736973506f6f6c3a2063616c6c6572206973206e6f74207460008201527f6865206f70657261746f72000000000000000000000000000000000000000000602082015250565b60006120ad602b83612040565b91506120b882612051565b604082019050919050565b600060208201905081810360008301526120dc816120a0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061214c82611c22565b915061215783611c22565b925082820390508181111561216f5761216e612112565b5b92915050565b600061218082611c22565b915061218b83611c22565b92508282019050808211156121a3576121a2612112565b5b92915050565b60006121b482611c22565b91506121bf83611c22565b92508282026121cd81611c22565b915082820484148315176121e4576121e3612112565b5b5092915050565b7f77697468647261773a206e6f7420676f6f640000000000000000000000000000600082015250565b6000612221601283612040565b915061222c826121eb565b602082019050919050565b6000602082019050818103600083015261225081612214565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061229182611c22565b915061229c83611c22565b9250826122ac576122ab612257565b5b828204905092915050565b60006040820190506122cc6000830185611ebe565b6122d96020830184611c2c565b9392505050565b6000815190506122ef81611ee8565b92915050565b60006020828403121561230b5761230a611c56565b5b6000612319848285016122e0565b91505092915050565b60008151905061233181611c5b565b92915050565b60006020828403121561234d5761234c611c56565b5b600061235b84828501612322565b91505092915050565b7f5875736400000000000000000000000000000000000000000000000000000000600082015250565b600061239a600483612040565b91506123a582612364565b602082019050919050565b600060208201905081810360008301526123c98161238d565b9050919050565b7f706f6f6c2e746f6b656e00000000000000000000000000000000000000000000600082015250565b6000612406600a83612040565b9150612411826123d0565b602082019050919050565b60006020820190508181036000830152612435816123f9565b9050919050565b60006060820190506124516000830186611ebe565b61245e6020830185611ebe565b61246b6040830184611c2c565b949350505050565b7f5875736447656e65736973506f6f6c3a206578697374696e6720706f6f6c3f00600082015250565b60006124a9601f83612040565b91506124b482612473565b602082019050919050565b600060208201905081810360008301526124d88161249c565b905091905056fea264697066735822122067c3f8dfcaa0dc5603356fabe736c6915763840db83a7995d991b8da97fe1d9f64736f6c634300081a0033000000000000000000000000bbea78397d4d4590882efcc4820f03074ab2ab2900000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066f2fa4200000000000000000000000000000000000000000073ce27351811f40c0000000000000000000000000000000000000000000000000000000000000000e6b6800000000000000000000000000000000000000000000000000000000000000000

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106101585760003560e01c80635f96dc11116100c357806392fae48d1161007c57806392fae48d146103a657806393f1a40b146103c4578063943f013d146103f5578063b3ab15fb14610413578063e2bbb1581461042f578063f25bb8651461044b57610158565b80635f96dc11146102f6578063628b409f1461031457806362e006c714610332578063630b5ba11461034e5780636e271dd5146103585780637805583c1461037657610158565b806351eb05a61161011557806351eb05a6146102365780635312ea8e1461025257806354575af41461026e578063570ca7351461028a5780635715f8f9146102a85780635b142956146102c657610158565b80630e15561a1461015d5780631526fe271461017b57806317caf6f1146101b05780631ab06ee5146101ce578063231f0c6a146101ea578063441a3e701461021a575b600080fd5b610165610469565b6040516101729190611c3b565b60405180910390f35b61019560048036038101906101909190611c87565b61046f565b6040516101a796959493929190611d4e565b60405180910390f35b6101b86104e8565b6040516101c59190611c3b565b60405180910390f35b6101e860048036038101906101e39190611daf565b6104ee565b005b61020460048036038101906101ff9190611daf565b6105f5565b6040516102119190611c3b565b60405180910390f35b610234600480360381019061022f9190611daf565b6106d0565b005b610250600480360381019061024b9190611c87565b610989565b005b61026c60048036038101906102679190611c87565b610b54565b005b61028860048036038101906102839190611e6b565b610ce3565b005b610292610f7b565b60405161029f9190611ecd565b60405180910390f35b6102b0610fa1565b6040516102bd9190611c3b565b60405180910390f35b6102e060048036038101906102db9190611c87565b610fa7565b6040516102ed9190611ecd565b60405180910390f35b6102fe610fc4565b60405161030b9190611c3b565b60405180910390f35b61031c610fca565b6040516103299190611c3b565b60405180910390f35b61034c60048036038101906103479190611f14565b610fd0565b005b610356611201565b005b61036061122e565b60405161036d9190611c3b565b60405180910390f35b610390600480360381019061038b9190611f8f565b611234565b60405161039d9190611c3b565b60405180910390f35b6103ae611413565b6040516103bb9190611c3b565b60405180910390f35b6103de60048036038101906103d99190611f8f565b611424565b6040516103ec929190611fcf565b60405180910390f35b6103fd611455565b60405161040a9190611c3b565b60405180910390f35b61042d60048036038101906104289190611ff8565b61145b565b005b61044960048036038101906104449190611daf565b61152f565b005b610453611867565b6040516104609190612025565b60405180910390f35b600c5481565b6005818154811061047f57600080fd5b90600052602060002090600602016000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020154908060030154908060040160009054906101000a900460ff16908060050154905086565b60075481565b3373ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461057e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610575906120c3565b60405180910390fd5b610586611201565b60006005838154811061059c5761059b6120e3565b5b906000526020600020906006020190508060040160009054906101000a900460ff16156105e7578181600101546007546105d69190612141565b6105e09190612175565b6007819055505b818160010181905550505050565b600081831061060757600090506106ca565b600954821061067157600954831061062257600090506106ca565b600854831161064f57600a5460085460095461063e9190612141565b61064891906121a9565b90506106ca565b600a54836009546106609190612141565b61066a91906121a9565b90506106ca565b600854821161068357600090506106ca565b60085483116106ae57600a546008548361069d9190612141565b6106a791906121a9565b90506106ca565b600a5483836106bd9190612141565b6106c791906121a9565b90505b92915050565b60003390506000600584815481106106eb576106ea6120e3565b5b9060005260206000209060060201905060006006600086815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508381600001541015610796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161078d90612237565b60405180910390fd5b61079f85610989565b60008160010154670de0b6b3a7640000846003015484600001546107c391906121a9565b6107cd9190612286565b6107d79190612141565b9050600081111561083b576107ec848261188d565b8373ffffffffffffffffffffffffffffffffffffffff167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486826040516108329190611c3b565b60405180910390a25b600085111561090357848260000160008282546108589190612141565b925050819055508260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85876040518363ffffffff1660e01b81526004016108be9291906122b7565b6020604051808303816000875af11580156108dd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090191906122f5565b505b670de0b6b3a76400008360030154836000015461092091906121a9565b61092a9190612286565b8260010181905550858473ffffffffffffffffffffffffffffffffffffffff167ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568876040516109799190611c3b565b60405180910390a3505050505050565b60006005828154811061099f5761099e6120e3565b5b90600052602060002090600602019050806002015442116109c05750610b51565b60008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610a1f9190611ecd565b602060405180830381865afa158015610a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a609190612337565b905060008103610a7a574282600201819055505050610b51565b8160040160009054906101000a900460ff16610acb5760018260040160006101000a81548160ff021916908315150217905550816001015460076000828254610ac39190612175565b925050819055505b60006007541115610b45576000610ae68360020154426105f5565b90506000600754846001015483610afd91906121a9565b610b079190612286565b905082670de0b6b3a764000082610b1e91906121a9565b610b289190612286565b846003016000828254610b3b9190612175565b9250508190555050505b42826002018190555050505b50565b600060058281548110610b6a57610b696120e3565b5b9060005260206000209060060201905060006006600084815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154905060008260000181905550600082600101819055508260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401610c4a9291906122b7565b6020604051808303816000875af1158015610c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8d91906122f5565b50833373ffffffffffffffffffffffffffffffffffffffff167fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae059583604051610cd59190611c3b565b60405180910390a350505050565b3373ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610d73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d6a906120c3565b60405180910390fd5b62278d00600954610d849190612175565b421015610ef757600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e12906123b0565b60405180910390fd5b6000600580549050905060005b81811015610ef457600060058281548110610e4657610e456120e3565b5b906000526020600020906006020190508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603610ee8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610edf9061241c565b60405180910390fd5b50806001019050610e28565b50505b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb82846040518363ffffffff1660e01b8152600401610f329291906122b7565b6020604051808303816000875af1158015610f51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7591906122f5565b50505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60025481565b6000610fbd826000611a8c90919063ffffffff16565b9050919050565b60085481565b600a5481565b3373ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611060576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611057906120c3565b60405180910390fd5b61106984611aa6565b821561107857611077611201565b5b6008544210156110aa57600082036110945760085491506110a5565b6008548210156110a45760085491505b5b6110c2565b60008214806110b857504282105b156110c1574291505b5b6000600854831115806110d55750428311155b905060056040518060c001604052808773ffffffffffffffffffffffffffffffffffffffff16815260200188815260200185815260200160008152602001831515815260200184815250908060018154018082558091505060019003906000526020600020906006020160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155604082015181600201556060820151816003015560808201518160040160006101000a81548160ff02191690831515021790555060a08201518160050155505080156111f95785600760008282546111f19190612175565b925050819055505b505050505050565b6000600580549050905060005b8181101561122a5761121f81610989565b80600101905061120e565b5050565b60095481565b6000806005848154811061124b5761124a6120e3565b5b9060005260206000209060060201905060006006600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008260030154905060008360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016113179190611ecd565b602060405180830381865afa158015611334573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113589190612337565b905083600201544211801561136e575060008114155b156113d55760006113838560020154426105f5565b9050600060075486600101548361139a91906121a9565b6113a49190612286565b905082670de0b6b3a7640000826113bb91906121a9565b6113c59190612286565b846113d09190612175565b935050505b8260010154670de0b6b3a76400008385600001546113f391906121a9565b6113fd9190612286565b6114079190612141565b94505050505092915050565b600061141f6000611b7e565b905090565b6006602052816000526040600020602052806000526040600020600091509150508060000154908060010154905082565b600b5481565b3373ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e2906120c3565b60405180910390fd5b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600033905060006005848154811061154a576115496120e3565b5b9060005260206000209060060201905060006006600086815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506115b785610989565b6000816000015411156116625760008160010154670de0b6b3a7640000846003015484600001546115e891906121a9565b6115f29190612286565b6115fc9190612141565b9050600081111561166057611611848261188d565b8373ffffffffffffffffffffffffffffffffffffffff167fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486826040516116579190611c3b565b60405180910390a25b505b6000816000015483600501546116789190612141565b90506000818611611689578561168b565b815b905060008111156117e0578360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd8630846040518463ffffffff1660e01b81526004016116f79392919061243c565b6020604051808303816000875af1158015611716573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173a91906122f5565b506117738460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000611b9390919063ffffffff16565b156117c35760006127109050806002548261178e9190612141565b8361179991906121a9565b6117a39190612286565b8460000160008282546117b69190612175565b92505081905550506117df565b808360000160008282546117d79190612175565b925050819055505b5b670de0b6b3a7640000846003015484600001546117fd91906121a9565b6118079190612286565b8360010181905550868573ffffffffffffffffffffffffffffffffffffffff167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15836040516118569190611c3b565b60405180910390a350505050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016118ea9190611ecd565b602060405180830381865afa158015611907573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061192b9190612337565b90506000811115611a8757808211156119e457600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84836040518363ffffffff1660e01b815260040161199b9291906122b7565b6020604051808303816000875af11580156119ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119de91906122f5565b50611a86565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401611a419291906122b7565b6020604051808303816000875af1158015611a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8491906122f5565b505b5b505050565b6000611a9b8360000183611bc3565b60001c905092915050565b6000600580549050905060005b81811015611b79578273ffffffffffffffffffffffffffffffffffffffff1660058281548110611ae657611ae56120e3565b5b906000526020600020906006020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603611b6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b65906124bf565b60405180910390fd5b806001019050611ab3565b505050565b6000611b8c82600001611bee565b9050919050565b6000611bbb836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611bff565b905092915050565b6000826000018281548110611bdb57611bda6120e3565b5b9060005260206000200154905092915050565b600081600001805490509050919050565b600080836001016000848152602001908152602001600020541415905092915050565b6000819050919050565b611c3581611c22565b82525050565b6000602082019050611c506000830184611c2c565b92915050565b600080fd5b611c6481611c22565b8114611c6f57600080fd5b50565b600081359050611c8181611c5b565b92915050565b600060208284031215611c9d57611c9c611c56565b5b6000611cab84828501611c72565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000611cf9611cf4611cef84611cb4565b611cd4565b611cb4565b9050919050565b6000611d0b82611cde565b9050919050565b6000611d1d82611d00565b9050919050565b611d2d81611d12565b82525050565b60008115159050919050565b611d4881611d33565b82525050565b600060c082019050611d636000830189611d24565b611d706020830188611c2c565b611d7d6040830187611c2c565b611d8a6060830186611c2c565b611d976080830185611d3f565b611da460a0830184611c2c565b979650505050505050565b60008060408385031215611dc657611dc5611c56565b5b6000611dd485828601611c72565b9250506020611de585828601611c72565b9150509250929050565b6000611dfa82611cb4565b9050919050565b6000611e0c82611def565b9050919050565b611e1c81611e01565b8114611e2757600080fd5b50565b600081359050611e3981611e13565b92915050565b611e4881611def565b8114611e5357600080fd5b50565b600081359050611e6581611e3f565b92915050565b600080600060608486031215611e8457611e83611c56565b5b6000611e9286828701611e2a565b9350506020611ea386828701611c72565b9250506040611eb486828701611e56565b9150509250925092565b611ec781611def565b82525050565b6000602082019050611ee26000830184611ebe565b92915050565b611ef181611d33565b8114611efc57600080fd5b50565b600081359050611f0e81611ee8565b92915050565b600080600080600060a08688031215611f3057611f2f611c56565b5b6000611f3e88828901611c72565b9550506020611f4f88828901611e2a565b9450506040611f6088828901611eff565b9350506060611f7188828901611c72565b9250506080611f8288828901611c72565b9150509295509295909350565b60008060408385031215611fa657611fa5611c56565b5b6000611fb485828601611c72565b9250506020611fc585828601611e56565b9150509250929050565b6000604082019050611fe46000830185611c2c565b611ff16020830184611c2c565b9392505050565b60006020828403121561200e5761200d611c56565b5b600061201c84828501611e56565b91505092915050565b600060208201905061203a6000830184611d24565b92915050565b600082825260208201905092915050565b7f5875736447656e65736973506f6f6c3a2063616c6c6572206973206e6f74207460008201527f6865206f70657261746f72000000000000000000000000000000000000000000602082015250565b60006120ad602b83612040565b91506120b882612051565b604082019050919050565b600060208201905081810360008301526120dc816120a0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061214c82611c22565b915061215783611c22565b925082820390508181111561216f5761216e612112565b5b92915050565b600061218082611c22565b915061218b83611c22565b92508282019050808211156121a3576121a2612112565b5b92915050565b60006121b482611c22565b91506121bf83611c22565b92508282026121cd81611c22565b915082820484148315176121e4576121e3612112565b5b5092915050565b7f77697468647261773a206e6f7420676f6f640000000000000000000000000000600082015250565b6000612221601283612040565b915061222c826121eb565b602082019050919050565b6000602082019050818103600083015261225081612214565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061229182611c22565b915061229c83611c22565b9250826122ac576122ab612257565b5b828204905092915050565b60006040820190506122cc6000830185611ebe565b6122d96020830184611c2c565b9392505050565b6000815190506122ef81611ee8565b92915050565b60006020828403121561230b5761230a611c56565b5b6000612319848285016122e0565b91505092915050565b60008151905061233181611c5b565b92915050565b60006020828403121561234d5761234c611c56565b5b600061235b84828501612322565b91505092915050565b7f5875736400000000000000000000000000000000000000000000000000000000600082015250565b600061239a600483612040565b91506123a582612364565b602082019050919050565b600060208201905081810360008301526123c98161238d565b9050919050565b7f706f6f6c2e746f6b656e00000000000000000000000000000000000000000000600082015250565b6000612406600a83612040565b9150612411826123d0565b602082019050919050565b60006020820190508181036000830152612435816123f9565b9050919050565b60006060820190506124516000830186611ebe565b61245e6020830185611ebe565b61246b6040830184611c2c565b949350505050565b7f5875736447656e65736973506f6f6c3a206578697374696e6720706f6f6c3f00600082015250565b60006124a9601f83612040565b91506124b482612473565b602082019050919050565b600060208201905081810360008301526124d88161249c565b905091905056fea264697066735822122067c3f8dfcaa0dc5603356fabe736c6915763840db83a7995d991b8da97fe1d9f64736f6c634300081a0033