false
true
0

Contract Address Details

0x3a37c64B56F0F7cF7F402688753B1692BB46BC32

Contract Name
tokenVault
Creator
0xc6eda6–db69f1 at 0x4ab976–a8eef6
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
116 Transactions
Transfers
0 Transfers
Gas Used
0
Last Balance Update
26042997
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
tokenVault




Optimization enabled
true
Compiler version
v0.8.20+commit.a1b79de6




Optimization runs
200
EVM Version
default




Verified at
2025-06-24T12:02:37.524504Z

Contract source code

// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
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);
}

// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/interfaces/IERC20.sol


// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;


// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/IERC165.sol


// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/interfaces/IERC165.sol


// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;


// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/interfaces/IERC1363.sol


// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)

pragma solidity ^0.8.20;



/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol


// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;



/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    /**
     * @dev An operation with an ERC-20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}

// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.4.0/contracts/security/ReentrancyGuard.sol


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

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

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

// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/IERC721Receiver.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.20;

/**
 * @title ERC-721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC-721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be
     * reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/IERC721.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.20;


/**
 * @dev Required interface of an ERC-721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC-721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
     *   {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the address zero.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

// File: DEGEN-main (9)/DEGEN-main/contracts/interface/IGovernor.sol


// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.8.0. SEE SOURCE BELOW. !!
pragma solidity >=0.7.0 <0.9.0;

interface IGovernor {
    event EnforceGovernor(
        address indexed _newGovernor,
        address indexed enforcer
    );
    event GiveRolloverBonus(
        address indexed recipient,
        uint256 amount,
        address indexed poolInto
    );
    event SetInflation(uint256 rewardPerBlock);

    function OINK() external view returns (address);

    function acPool1() external view returns (address);

    function acPool1ID() external view returns (uint256);

    function acPool2() external view returns (address);

    function acPool2ID() external view returns (uint256);

    function acPool3() external view returns (address);

    function acPool3ID() external view returns (uint256);

    function acPool4() external view returns (address);

    function acPool4ID() external view returns (uint256);

    function addNewPool(address _pool) external;

    function addressToUint256(address addr) external pure returns (uint256);

    function basicContract() external view returns (address);

    function blockGovernorProposal() external;

    function burnTokens(uint256 _amount) external;

    function changedName() external view returns (bool);

    function consensusContract() external view returns (address);

    function costToVote() external view returns (uint256);

    function creditContract() external view returns (address);

    function delayBeforeEnforce() external view returns (uint256);

    function depositFee() external view returns (uint256);

    function farmContract() external view returns (address);

    function fundingRate() external view returns (uint256);

    function getRollBonus(address _bonusForPool)
        external
        view
        returns (uint256);

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

    function harvest() external;

    function manageRewardsAddress() external view returns (address);

    function helperToken() external view returns (address);

    function lastHarvestedTime() external view returns (uint256);

    function masterchef() external view returns (address);

    function proposeGovernorTimestamp() external view returns (uint256);

    function proposeNewGovernor(address beneficiary) external;

    function proposedGovernor() external view returns (address);

    function rebalancePools() external;

    function referralBonus() external view returns (uint256);

    function rewardContract() external view returns (address);

    function setCallFee(address _acPool, uint256 _newCallFee) external;

    function setGovernorTax(uint256 _amount) external;

    function setNewGovernor() external;

    function setNewGovernor2(address _new) external;

    function setPool(
        uint256 _pid,
        uint256 _allocPoint,
        bool _withUpdate
    ) external;

    function setReward(uint256 _amount) external;

    function stakeRolloverBonus(
        address _toAddress,
        address _depositToPool,
        uint256 _bonusToPay,
        uint256 _stakeID
    ) external;

    function token() external view returns (address);

    function transferToTreasury(uint256 amount) external;

    function treasuryRequest(
        address _tokenAddr,
        address _recipient,
        uint256 _amountToSend
    ) external;

    function treasuryWallet() external view returns (address);

    function updateCostToVote(uint256 newCostToVote) external;

    function updateDelayBeforeEnforce(uint256 newDelay) external;

    function updateRolloverBonus(address _forPool, uint256 _bonus) external;

    function updateVault(uint256 _type, uint256 _amount) external;
}

// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:
/*
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_newGovernor","type":"address"},{"indexed":true,"internalType":"address","name":"enforcer","type":"address"}],"name":"EnforceGovernor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"poolInto","type":"address"}],"name":"GiveRolloverBonus","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"rewardPerBlock","type":"uint256"}],"name":"SetInflation","type":"event"},{"inputs":[],"name":"OINK","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acPool1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acPool1ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acPool2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acPool2ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acPool3","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acPool3ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acPool4","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acPool4ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"addNewPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"addressToUint256","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"basicContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockGovernorProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burnTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"changedName","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"consensusContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"costToVote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"creditContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delayBeforeEnforce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"farmContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fundingRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bonusForPool","type":"address"}],"name":"getRollBonus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"governorBlocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"helperToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastHarvestedTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"masterchef","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposeGovernorTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"}],"name":"proposeNewGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proposedGovernor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalancePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"referralBonus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_acPool","type":"address"},{"internalType":"uint256","name":"_newCallFee","type":"uint256"}],"name":"setCallFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setGovernorTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setNewGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_new","type":"address"}],"name":"setNewGovernor2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"bool","name":"_withUpdate","type":"bool"}],"name":"setPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_toAddress","type":"address"},{"internalType":"address","name":"_depositToPool","type":"address"},{"internalType":"uint256","name":"_bonusToPay","type":"uint256"},{"internalType":"uint256","name":"_stakeID","type":"uint256"}],"name":"stakeRolloverBonus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferToTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddr","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amountToSend","type":"uint256"}],"name":"treasuryRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasuryWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCostToVote","type":"uint256"}],"name":"updateCostToVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newDelay","type":"uint256"}],"name":"updateDelayBeforeEnforce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_forPool","type":"address"},{"internalType":"uint256","name":"_bonus","type":"uint256"}],"name":"updateRolloverBonus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_type","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"updateVault","outputs":[],"stateMutability":"nonpayable","type":"function"}]
*/

// File: DEGEN-main (9)/DEGEN-main/contracts/interface/IMasterChef.sol


// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.8.0. SEE SOURCE BELOW. !!
pragma solidity ^0.8.20;

interface IMasterChef {
    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );
    event TransferCredit(address from, address to, uint256 amount);
    event TrustedContract(address contractAddress, bool setting);
    event UpdateEmissions(address indexed user, uint256 newEmissions);

    function DTXPerBlock() external view returns (uint256);

    function add(
        uint256 _allocPoint,
        address _participant,
        bool _withUpdate
    ) external;

    function burn(address _from, uint256 _amount) external returns (bool);

    function credit(address) external view returns (uint256);

    function dev(address _devaddr) external;

    function devaddr() external view returns (address);

    function dtx() external view returns (address);

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

    function fairMintSenate() external;

    function fairTokensPublishedToSenate() external view returns (uint256);

    function feeAddress() external view returns (address);

    function governorFee() external view returns (uint256);

    function massAdd(
        uint256[] memory _allocPoint,
        address[] memory _participant,
        bool[] memory _withUpdate
    ) external;

    function massUpdatePools() external;

    function owner() external view returns (address);

    function pendingDtx(uint256 _pid) external view returns (uint256);

    function poolInfo(uint256)
        external
        view
        returns (
            uint256 allocPoint,
            uint256 lastRewardBlock,
            address participant
        );

    function poolLength() external view returns (uint256);

    function publishTokens(address _to, uint256 _amount) external;

    function renounceOwnership() external;

    function renounceRewards() external;

    function rewardSenators(bool _e) external;

    function senatorRewards() external view returns (bool);

    function set(
        uint256 _pid,
        uint256 _allocPoint,
        bool _withUpdate
    ) external;

    function setFeeAddress(address _feeAddress) external;

    function setGovernorFee(uint256 _amount) external;

    function setTrustedContract(address _contractAddress, bool _setting)
        external;

    function startBlock() external view returns (uint256);

    function startPublishing(
        uint256 _pid,
        address _participant,
        uint256 _alloc
    ) external;

    function stopPublishing(uint256 _pid) external;

    function tokenChangeOwnership(address _newOwner) external;

    function totalAllocPoint() external view returns (uint256);

    function totalCreditRewards() external view returns (uint256);

    function totalCreditRewardsAtLastFairMint() external view returns (uint256);

    function totalPrincipalBurned() external view returns (uint256);

    function totalPublished() external view returns (uint256);

    function transferCredit(address _to, uint256 _amount) external;

    function transferOwnership(address newOwner) external;

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

    function trustedContractCount() external view returns (uint256);

    function updateEmissionRate(uint256 _DTXPerBlock) external;

    function updatePool(uint256 _pid) external;

    function updateStartBlock(uint256 _startBlock) external;

    function virtualTotalSupply() external view returns (uint256);
}

// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:
/*
[{"inputs":[{"internalType":"contract IDTX","name":"_DTX","type":"address"},{"internalType":"address","name":"_airdropFull","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferCredit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"setting","type":"bool"}],"name":"TrustedContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"newEmissions","type":"uint256"}],"name":"UpdateEmissions","type":"event"},{"inputs":[],"name":"DTXPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"address","name":"_participant","type":"address"},{"internalType":"bool","name":"_withUpdate","type":"bool"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"credit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_devaddr","type":"address"}],"name":"dev","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"devaddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dtx","outputs":[{"internalType":"contract IDTX","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"existingParticipant","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fairMintSenate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fairTokensPublishedToSenate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governorFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_allocPoint","type":"uint256[]"},{"internalType":"address[]","name":"_participant","type":"address[]"},{"internalType":"bool[]","name":"_withUpdate","type":"bool[]"}],"name":"massAdd","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"pendingDtx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"internalType":"address","name":"participant","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"publishTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_e","type":"bool"}],"name":"rewardSenators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"senatorRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"bool","name":"_withUpdate","type":"bool"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeAddress","type":"address"}],"name":"setFeeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setGovernorFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contractAddress","type":"address"},{"internalType":"bool","name":"_setting","type":"bool"}],"name":"setTrustedContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_participant","type":"address"},{"internalType":"uint256","name":"_alloc","type":"uint256"}],"name":"startPublishing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"stopPublishing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"tokenChangeOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalAllocPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalCreditRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalCreditRewardsAtLastFairMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPrincipalBurned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPublished","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferCredit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"trustedContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedContractCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_DTXPerBlock","type":"uint256"}],"name":"updateEmissionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_startBlock","type":"uint256"}],"name":"updateStartBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"virtualTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
*/

// File: DEGEN-main (9)/DEGEN-main/contracts/interface/IacPool.sol


// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.8.0. SEE SOURCE BELOW. !!
pragma solidity >=0.7.0 <0.9.0;

interface IacPool {
    event AddAndExtendStake(
        address indexed sender,
        address indexed recipient,
        uint256 amount,
        uint256 stakeID,
        uint256 shares,
        uint256 lastDepositedTime
    );
    event AddVotes(address indexed voter, uint256 proposalID, uint256 change);
    event Deposit(
        address indexed sender,
        uint256 amount,
        uint256 shares,
        uint256 lastDepositedTime
    );
    event GiftDeposit(
        address indexed sender,
        address indexed recipient,
        uint256 amount,
        uint256 shares,
        uint256 lastDepositedTime
    );
    event HopDeposit(
        address indexed recipient,
        uint256 amount,
        uint256 shares,
        uint256 previousLastDepositedTime,
        uint256 mandatoryTime
    );
    event HopPool(
        address indexed sender,
        uint256 DTXamount,
        uint256 shares,
        address indexed newPool
    );
    event MigrateStake(
        address indexed goodSamaritan,
        uint256 DTXamount,
        uint256 shares,
        address indexed recipient
    );
    event RemoveVotes(
        address indexed voter,
        uint256 proposalID,
        uint256 change
    );
    event SetDelegate(address userDelegating, address delegatee);
    event StakeAllowanceRevoke(
        address owner,
        address spender,
        uint256 allowanceID
    );
    event StakeApproval(
        address owner,
        address spender,
        uint256 allowanceID,
        uint256 shareAllowance,
        uint256 lastDeposit,
        uint256 mandatoryTime
    );
    event TransferStake(
        address indexed sender,
        address indexed recipient,
        uint256 shares,
        uint256 stakeID
    );
    event TransferStakeFrom(
        address _from,
        address _to,
        uint256 _stakeID,
        uint256 _allowanceID
    );
    event TrustedPool(address contractAddress, bool setting);
    event TrustedSender(address contractAddress, bool setting);
    event Withdraw(
        address indexed sender,
        uint256 amount,
        uint256 penalty,
        uint256 shares
    );

    function addAndExtendStake(
        address _recipientAddr,
        uint256 _amount,
        uint256 _stakeID,
        uint256 _lockUpTokensInSeconds
    ) external;

    function admin() external view returns (address);

    function allowOrigin() external view returns (bool);

    function allowStakeTransfer() external view returns (bool);

    function allowStakeTransferFrom() external view returns (bool);

    function allowTxOrigin(bool _setting) external;

    function balanceOf() external view returns (uint256);

    function calculateHarvestDTXRewards() external view returns (uint256);

    function calculateTotalPendingDTXRewards() external view returns (uint256);

    function callFee() external view returns (uint256);

    function delegateeVote(address[] memory votingAddress, uint256 proposalID)
        external;

    function deposit(uint256 _amount) external;

    function enableDisableStakeTransfer(bool _setting) external;

    function enableDisableStakeTransferFrom(bool _setting) external;

    function getNrOfStakes(address _user) external view returns (uint256);

    function getPricePerFullShare() external view returns (uint256);

    function getUserShares(address _wallet, uint256 _stakeID)
        external
        view
        returns (uint256);

    function getUserTotalShares(address _user) external view returns (uint256);

    function giftDeposit(
        uint256 _amount,
        address _toAddress,
        uint256 _minToServeInSecs
    ) external;

    function giveStakeAllowance(address spender, uint256 _stakeID) external;

    function gracePeriod() external view returns (uint256);

    function hopDeposit(
        uint256 _amount,
        address _recipientAddress,
        uint256 previousLastDepositedTime,
        uint256 _mandatoryTime
    ) external;

    function hopStakeToAnotherPool(
        uint256 _shares,
        uint256 _stakeID,
        address _poolAddress
    ) external;

    function masterchef() external view returns (address);

    function migrateAllStakes(address _staker) external;

    function migrateStake(address _staker, uint256 _stakeID) external;

    function migrationPool() external view returns (address);

    function minimumGift() external view returns (uint256);

    function modifyPartialTransfers(bool _decision) external;

    function modifyPartialWithdrawals(bool _decision) external;

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

    function partialTransfers() external view returns (bool);

    function partialWithdrawals() external view returns (bool);

    function poolID() external view returns (uint256);

    function revokeStakeAllowance(address spender, uint256 allowanceID)
        external;

    function setAdmin() external;

    function setCallFee(uint256 _callFee) external;

    function setDelegate(address _delegate, bool asProxy) external;

    function setMasterChefAddress(address _masterchef, uint256 _newPoolID)
        external;

    function setMigrationPool(address _newPool) external;

    function setMinimumGiftDeposit(uint256 _amount, bool _setting) external;

    function setTrustedPool(address[] memory _pool, bool _setting) external;

    function setTrustedSender(address[] memory _sender, bool _setting) external;

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

    function stakeRollover(address _poolInto, uint256 _stakeID) external;

    function token() external view returns (address);

    function totalShares() external view returns (uint256);

    function totalVotesForID(uint256) external view returns (uint256);

    function transferStakeFrom(
        address _from,
        uint256 _stakeID,
        uint256 allowanceID,
        address _to
    ) external returns (bool);

    function transferStakeToAnotherWallet(
        uint256 _shares,
        uint256 _stakeID,
        address _recipientAddress
    ) external;

    function treasury() external view returns (address);

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

    function trustedPoolCount() external view returns (uint256);

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

    function trustedSenderCount() external view returns (uint256);

    function updateMinGiftGovernor() external view returns (bool);

    function updateMinimumGift() external;

    function userDelegate(address) external view returns (address);

    function userInfo(address, uint256)
        external
        view
        returns (
            uint256 shares,
            uint256 lastDepositedTime,
            uint256 dtxAtLastUserAction,
            uint256 lastUserActionTime,
            uint256 mandatoryTimeToServe
        );

    function userVote(address) external view returns (uint256);

    function voteForProposal(uint256 proposalID, bool asProxy) external;

    function votingCredit(uint256 _shares, uint256 _stakeID) external;

    function votingCreditAddress() external view returns (address);

    function withdraw(uint256 _shares, uint256 _stakeID) external;

    function withdrawAll(uint256 _stakeID) external;

    function withdrawFeePeriod() external view returns (uint256);

    function withdrawStuckTokens(address _tokenAddress) external;
}

// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:
/*
[{"inputs":[{"internalType":"contract IDTX","name":"_token","type":"address"},{"internalType":"contract IMasterChef","name":"_masterchef","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakeID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastDepositedTime","type":"uint256"}],"name":"AddAndExtendStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"proposalID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"change","type":"uint256"}],"name":"AddVotes","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastDepositedTime","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastDepositedTime","type":"uint256"}],"name":"GiftDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"previousLastDepositedTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mandatoryTime","type":"uint256"}],"name":"HopDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"DTXamount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":true,"internalType":"address","name":"newPool","type":"address"}],"name":"HopPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"goodSamaritan","type":"address"},{"indexed":false,"internalType":"uint256","name":"DTXamount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"MigrateStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"proposalID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"change","type":"uint256"}],"name":"RemoveVotes","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userDelegating","type":"address"},{"indexed":false,"internalType":"address","name":"delegatee","type":"address"}],"name":"SetDelegate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"allowanceID","type":"uint256"}],"name":"StakeAllowanceRevoke","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"allowanceID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shareAllowance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastDeposit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mandatoryTime","type":"uint256"}],"name":"StakeApproval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakeID","type":"uint256"}],"name":"TransferStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_stakeID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_allowanceID","type":"uint256"}],"name":"TransferStakeFrom","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"setting","type":"bool"}],"name":"TrustedPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"setting","type":"bool"}],"name":"TrustedSender","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"penalty","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"_recipientAddr","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_stakeID","type":"uint256"},{"internalType":"uint256","name":"_lockUpTokensInSeconds","type":"uint256"}],"name":"addAndExtendStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowOrigin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowStakeTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowStakeTransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_setting","type":"bool"}],"name":"allowTxOrigin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculateHarvestDTXRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculateTotalPendingDTXRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"votingAddress","type":"address[]"},{"internalType":"uint256","name":"proposalID","type":"uint256"}],"name":"delegateeVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_setting","type":"bool"}],"name":"enableDisableStakeTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_setting","type":"bool"}],"name":"enableDisableStakeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getNrOfStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPricePerFullShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"},{"internalType":"uint256","name":"_stakeID","type":"uint256"}],"name":"getUserShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getUserTotalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_toAddress","type":"address"},{"internalType":"uint256","name":"_minToServeInSecs","type":"uint256"}],"name":"giftDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"_stakeID","type":"uint256"}],"name":"giveStakeAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gracePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_recipientAddress","type":"address"},{"internalType":"uint256","name":"previousLastDepositedTime","type":"uint256"},{"internalType":"uint256","name":"_mandatoryTime","type":"uint256"}],"name":"hopDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"},{"internalType":"uint256","name":"_stakeID","type":"uint256"},{"internalType":"address","name":"_poolAddress","type":"address"}],"name":"hopStakeToAnotherPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"masterchef","outputs":[{"internalType":"contract IMasterChef","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"migrateAllStakes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"uint256","name":"_stakeID","type":"uint256"}],"name":"migrateStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"migrationPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumGift","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_decision","type":"bool"}],"name":"modifyPartialTransfers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_decision","type":"bool"}],"name":"modifyPartialWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"nrOfstakeAllowances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"partialTransfers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"partialWithdrawals","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowanceID","type":"uint256"}],"name":"revokeStakeAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_callFee","type":"uint256"}],"name":"setCallFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"},{"internalType":"bool","name":"asProxy","type":"bool"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IMasterChef","name":"_masterchef","type":"address"},{"internalType":"uint256","name":"_newPoolID","type":"uint256"}],"name":"setMasterChefAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPool","type":"address"}],"name":"setMigrationPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_setting","type":"bool"}],"name":"setMinimumGiftDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_pool","type":"address[]"},{"internalType":"bool","name":"_setting","type":"bool"}],"name":"setTrustedPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_sender","type":"address[]"},{"internalType":"bool","name":"_setting","type":"bool"}],"name":"setTrustedSender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowanceID","type":"uint256"}],"name":"stakeAllowances","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolInto","type":"address"},{"internalType":"uint256","name":"_stakeID","type":"uint256"}],"name":"stakeRollover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IDTX","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalVotesForID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_stakeID","type":"uint256"},{"internalType":"uint256","name":"allowanceID","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"transferStakeFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"},{"internalType":"uint256","name":"_stakeID","type":"uint256"},{"internalType":"address","name":"_recipientAddress","type":"address"}],"name":"transferStakeToAnotherWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"trustedPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedPoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"trustedSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedSenderCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updateMinGiftGovernor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updateMinimumGift","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userDelegate","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"lastDepositedTime","type":"uint256"},{"internalType":"uint256","name":"dtxAtLastUserAction","type":"uint256"},{"internalType":"uint256","name":"lastUserActionTime","type":"uint256"},{"internalType":"uint256","name":"mandatoryTimeToServe","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userVote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalID","type":"uint256"},{"internalType":"bool","name":"asProxy","type":"bool"}],"name":"voteForProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"},{"internalType":"uint256","name":"_stakeID","type":"uint256"}],"name":"votingCredit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"votingCreditAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"},{"internalType":"uint256","name":"_stakeID","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakeID","type":"uint256"}],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawFeePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"withdrawStuckTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]
*/

// File: DEGEN-main (9)/DEGEN-main/contracts/interface/IDTX.sol


// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.8.0. SEE SOURCE BELOW. !!
pragma solidity ^0.8.20;

interface IDTX {
    error ERC20InsufficientAllowance(
        address spender,
        uint256 allowance,
        uint256 needed
    );
    error ERC20InsufficientBalance(
        address sender,
        uint256 balance,
        uint256 needed
    );
    error ERC20InvalidApprover(address approver);
    error ERC20InvalidReceiver(address receiver);
    error ERC20InvalidSender(address sender);
    error ERC20InvalidSpender(address spender);
    error OwnableInvalidOwner(address owner);
    error OwnableUnauthorizedAccount(address account);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );
    event Transfer(address indexed from, address indexed to, uint256 value);

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

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

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

    function burn(uint256 value) external;

    function burnFrom(address account, uint256 value) external;

    function burnToken(address account, uint256 amount) external returns (bool);

    function decimals() external view returns (uint8);

    function governor() external view returns (address);

    function masterchefAddress() external view returns (address);

    function mint(address to, uint256 amount) external;

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

    function owner() external view returns (address);

    function rebrandName(string memory _newName) external;

    function rebrandSymbol(string memory _newSymbol) external;

    function receiveTax() external view returns (address);

    function renounceOwnership() external;

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

    function tax() external view returns (uint256);

    function totalSupply() external view returns (uint256);

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

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

    function transferOwnership(address newOwner) external;

    function updateTax(address _taxAddress) external;

    function updateTax(uint256 _tax) external;
}

// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:
/*
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"masterchefAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_newName","type":"string"}],"name":"rebrandName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newSymbol","type":"string"}],"name":"rebrandSymbol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"receiveTax","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_taxAddress","type":"address"}],"name":"updateTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tax","type":"uint256"}],"name":"updateTax","outputs":[],"stateMutability":"nonpayable","type":"function"}]
*/

// File: DEGEN-main (9)/DEGEN-main/contracts/pulse-ecosystem/vaultStrategy13.sol



pragma solidity 0.8.20;










interface IHelperToken {
	function mint(address to, uint256 amount) external;
}

interface IEmit {
    event Deposit(address indexed user, uint256 indexed pid, uint256 amount);
    event EmergencyWithdraw(
        address indexed user,
        uint256 indexed pid,
        uint256 amount
    );
    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );
    event RewardPaid(address indexed user, uint256 amount);
    event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);

    function BBC() external view returns (address);

    function INC() external view returns (address);

    function MAX_REWARDS_PER_SEC() external view returns (uint256);

    function NINE_INCH_MASTERCHEF() external view returns (address);

    function PULSE_X_MASTERCHEF() external view returns (address);

    function add(
        uint256 _allocPoint,
        address _token,
        bool _withUpdate,
        uint256 _lastRewardTime,
        uint16 _depositFeeBP,
        uint16 _withdrawFeeBP,
        uint8 _externalProtocol,
        address _externalFarm,
        uint256 _externalPid
    ) external;

    function deposit(
        uint256 _pid,
        uint256 _amount,
        address _referrer
    ) external;

    function depositOnBehalfOf(
        uint256 _pid,
        uint256 _amount,
        address _referrer,
        address _staker
    ) external;

    function devAddress() external view returns (address);

    function devPercent() external view returns (uint256);

    function emergencyWithdraw(uint256 _pid) external;

    function emitToken() external view returns (address);

    function emittersNft() external view returns (address);

    function feeAddress() external view returns (address);

    function feePercent() external view returns (uint256);

    function getAllPoolViews()
        external
        view
        returns (EMISSIONS.PoolView[] memory);

    function getExternalReward(uint256 _pid) external;

    function getMultiplier(uint256 _from, uint256 _to)
        external
        view
        returns (uint256);

    function getPoolView(uint256 pid)
        external
        view
        returns (EMISSIONS.PoolView memory);

    function getUserView(uint256 pid, address account)
        external
        view
        returns (EMISSIONS.UserView memory);

    function getUserViews(address account)
        external
        view
        returns (EMISSIONS.UserView[] memory);

    function massUpdatePools() external;

    function multicall(bytes[] memory data)
        external
        returns (bytes[] memory results);

    function owner() external view returns (address);

    function pendingShare(uint256 _pid, address _user)
        external
        view
        returns (uint256);

    function poolInfo(uint256)
        external
        view
        returns (
            address token,
            uint256 allocPoint,
            uint256 lastRewardTime,
            uint16 depositFeeBP,
            uint16 withdrawFeeBP,
            uint256 accTokensPerShare,
            bool isStarted,
            uint8 externalProtocol,
            address externalFarm,
            uint256 lpBalance,
            uint256 externalPid
        );

    function poolLength() external view returns (uint256);

    function referral(address) external view returns (address);

    function referralEarned(address) external view returns (uint256);

    function referralRate() external view returns (uint256);

    function removeExternalFarm(uint256 _pid) external;

    function renounceOwnership() external;

    function rewardsPerSec() external view returns (uint256);

    function set(
        uint256 _pid,
        uint256 _allocPoint,
        uint16 _depositFeeBP,
        uint16 _withdrawFeeBP
    ) external;

    function setDevAddress(address _devAddress) external;

    function setDevPercent(uint256 _devPercent) external;

    function setFeeAddress(address _feeAddress) external;

    function setFeePercent(uint256 _feePercent) external;

    function setReferralRate(uint256 _referralRate) external;

    function startTime() external view returns (uint256);

    function totalAllocPoint() external view returns (uint256);

    function transferOwnership(address newOwner) external;

    function updateEmissionRate(uint256 _rewardsPerSec) external;

    function updatePool(uint256 _pid) external;

    function userInfo(uint256, address)
        external
        view
        returns (uint256 amount, uint256 rewardDebt);

    function withdraw(uint256 _pid, uint256 _amount) external;
}

interface EMISSIONS {
    struct PoolView {
        uint256 pid;
        address token;
        uint256 allocPoint;
        uint256 lastRewardTime;
        uint16 depositFeeBP;
        uint16 withdrawFeeBP;
        uint256 accTokensPerShare;
        bool isStarted;
        uint8 externalProtocol;
        address externalFarm;
        uint256 lpBalance;
        uint256 rewardsPerSecond;
    }

    struct UserView {
        uint256 pid;
        uint256 stakedAmount;
        uint256 unclaimedRewards;
        uint256 lpBalance;
        uint256 allowance;
    }
}



/**
 * Token vault (hex, inc, plsx)
 */
contract tokenVault is ReentrancyGuard, IERC721Receiver {
    using SafeERC20 for IERC20;

    struct UserInfo {
        uint256 amount;
		uint256 debt;
		uint256 feesPaid;
		uint256 lastAction;
    }
	
	uint256 public constant maxFee = 2500; // max 25%
	uint256 public constant maxFundingFee = 1000; // max 0.1% per hour
	
    address public immutable token; //  token

    IERC20 public immutable stakeToken; // plsx, inc, hex

    IMasterChef public masterchef;  

	uint256 public vaultBalance = 0; //commissions belonging to the vault

	address public emitChef = 0x7Cc0a0ca2f9346AceAdd5110cfa15C4FA12f9251; // "emissions contract"
	address public rewardToken = 0x32fB5663619A657839A80133994E45c5e5cDf427; // == EMIT

    IERC721 public nftContract = IERC721(0x133F4205141d869A72724910331c0f0b7235dF7b);
    uint256 public nftId = 268;

    bool public useNFT = true;

    uint256 public constant emissionsPoolId = 10; //pool id in emissions contract

	address public manageRewardsAddress;
    address public helperToken;

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

	// Referral system: Track referrer + referral points
	mapping(address => address) public referredBy;
	mapping(address => uint256) public referralPoints;

	uint256 public poolID; 
	uint256 public actuatorPoolId;
	uint256 public accDtxPerShare;
	address public treasuryWallet; // Actual treasury wallet

	uint256 public lastCredit; // Keep track of our latest credit score from masterchef
	
	uint256 public depositFee = 0; // 0
	uint256 public fundingRate = 0;// 0
	uint256 public lastFundingChangeTimestamp; // save block.timestamp when funding rate is changed
	

    event Deposit(address indexed sender, uint256 amount, uint256 debt, uint256 depositFee, address indexed referral);
    event Withdraw(address indexed sender, uint256 stakeID, uint256 harvestAmount);

    event SelfHarvest(address indexed user, uint256 harvestAmount);
	
	event CollectedFee(address indexed from, uint256 amount);

 
    constructor() {
        stakeToken = IERC20(0x46814b3f18D90625B6E166bC2917Bb64a635d797); // vpls-pls
        poolID = 16;
	token = 0x3E79130ab714E97ee73f86a56a2427bb1A519896;


	IERC20(stakeToken).approve(emitChef, type(uint256).max);
    }
    
    /**
     * @notice Checks if the msg.sender is the admin
     */
    modifier decentralizedVoting() {
        require(msg.sender == IMasterChef(masterchef).owner(), "Decentralized Voting Only!");
        _;
    }

	
    /**
     * Creates a NEW stake
     */
    function deposit(uint256 _amount, address referral) external nonReentrant {
        require(_amount > 0, "invalid amount");
        harvest();
		stakeToken.safeTransferFrom(msg.sender, address(this), _amount);
		
		if(referredBy[msg.sender] == address(0) && referral != msg.sender) {
			referredBy[msg.sender] = referral;
		}

		uint256 _depositFee = 0;
		if(depositFee != 0) {
			_depositFee = _amount * depositFee / 10000;
			_amount = _amount - _depositFee;
		
        	stakeToken.safeTransfer(treasuryWallet, _depositFee);
		}
		
		uint256 _debt = accDtxPerShare;

        if(useNFT) {
            address _nftOwner = nftContract.ownerOf(nftId);
            if(_nftOwner != address(this)) {
                nftContract.safeTransferFrom(_nftOwner, address(this), nftId);
            }
        }
        EMISSIONS.UserView memory userView = IEmit(emitChef).getUserView(emissionsPoolId, address(this));
		uint256 _before = userView.stakedAmount;
		IEmit(emitChef).deposit(emissionsPoolId, _amount, 0x6494d2569b81E5a6164212E641331A530a150c3b);
        userView = IEmit(emitChef).getUserView(emissionsPoolId, address(this));
		uint256 _after = userView.stakedAmount;
		uint256 _userAmount = _after - _before;

        userInfo[msg.sender].push(
                UserInfo(_userAmount, _debt, _depositFee, block.timestamp)
            );

        emit Deposit(msg.sender, _amount, _debt, _depositFee, referredBy[msg.sender]);
    }

    /**
     * Harvests into pool
     */
    function harvest() public {
        IMasterChef(masterchef).updatePool(poolID);
		uint256 _currentCredit = IMasterChef(masterchef).credit(address(this));
		uint256 _accumulatedRewards = _currentCredit - lastCredit;
		lastCredit = _currentCredit;
        EMISSIONS.UserView memory userView = IEmit(emitChef).getUserView(emissionsPoolId, address(this));
		uint256 _amount = userView.stakedAmount;
		accDtxPerShare+= _accumulatedRewards * 1e12  / (_amount - vaultBalance);
    }

	function initialize() external {
        EMISSIONS.UserView memory userView = IEmit(emitChef).getUserView(emissionsPoolId, address(this));
		uint256 _amount = userView.stakedAmount;
		require(_amount == 0, "only initialization allowed");
		IEmit(emitChef).deposit(emissionsPoolId, 1, 0x6494d2569b81E5a6164212E641331A530a150c3b);
	}

	// what to do with the accumulated rewards here
	function useRewards() external {
		IEmit(emitChef).deposit(emissionsPoolId, 0, 0x6494d2569b81E5a6164212E641331A530a150c3b);
		IERC20(rewardToken).transfer(manageRewardsAddress, IERC20(rewardToken).balanceOf(address(this)));
}


    /**
     * Withdraws all tokens
     */
    function withdraw(uint256 _stakeID) public nonReentrant {
        harvest();
        require(_stakeID < userInfo[msg.sender].length, "invalid stake ID");
        UserInfo storage user = userInfo[msg.sender][_stakeID];

		
		payFee(user, msg.sender);

		uint256 _before = IERC20(stakeToken).balanceOf(address(this));
		IEmit(emitChef).withdraw(emissionsPoolId, user.amount);
		uint256 _after = IERC20(stakeToken).balanceOf(address(this));
		uint256 userTokens = _after - _before;
		uint256 currentAmount = user.amount * (accDtxPerShare - user.debt) / 1e12;

		
		_removeStake(msg.sender, _stakeID);

		IMasterChef(masterchef).transferCredit(helperToken, currentAmount);
		IHelperToken(helperToken).mint(msg.sender, currentAmount);

		if(referredBy[msg.sender] != address(0)) {
			referralPoints[msg.sender]+= currentAmount;
			referralPoints[referredBy[msg.sender]]+= currentAmount;
		}

		lastCredit = lastCredit - currentAmount;
		
		emit Withdraw(msg.sender, _stakeID, currentAmount);

        stakeToken.safeTransfer(msg.sender, userTokens);
    } 

	function selfHarvest(address _userAddress, uint256[] calldata _stakeID) external nonReentrant {
        require(_stakeID.length <= userInfo[_userAddress].length, "incorrect Stake list");
        UserInfo[] storage user = userInfo[_userAddress];
        harvest();
        uint256 _toWithdraw = 0;

        for(uint256 i = 0; i<_stakeID.length; ++i) {
		payFee(user[_stakeID[i]], _userAddress);
            _toWithdraw+= user[_stakeID[i]].amount * (accDtxPerShare - user[_stakeID[i]].debt)/ 1e12;
			user[_stakeID[i]].debt = accDtxPerShare;
        }

        IMasterChef(masterchef).transferCredit(helperToken, _toWithdraw);
		IHelperToken(helperToken).mint(_userAddress, _toWithdraw);

		if(referredBy[_userAddress] != address(0)) {
			referralPoints[_userAddress]+= _toWithdraw;
			referralPoints[referredBy[_userAddress]]+= _toWithdraw;
		}
		
		lastCredit = lastCredit - _toWithdraw;

		emit SelfHarvest(_userAddress, _toWithdraw);        
    }

	// emergency withdraw, without caring about rewards
	function emergencyWithdraw(uint256 _stakeID) public nonReentrant {
		require(_stakeID < userInfo[msg.sender].length, "invalid stake ID");
		UserInfo storage user = userInfo[msg.sender][_stakeID];

        payFee(user, msg.sender);
		//if there is withdraw fee
		uint256 _before = IERC20(stakeToken).balanceOf(address(this));
        IEmit(emitChef).withdraw(emissionsPoolId, user.amount);
		uint256 _after = IERC20(stakeToken).balanceOf(address(this));
		uint256 _amount = _after - _before;
		
		_removeStake(msg.sender, _stakeID); //delete the stake
        emit Withdraw(msg.sender, _stakeID, _amount);
        stakeToken.safeTransfer(msg.sender, _amount);
	}

	function emergencyWithdrawAll() external {
		uint256 _stakeID = userInfo[msg.sender].length;
		while(_stakeID > 0) {
			_stakeID--;
			emergencyWithdraw(_stakeID);
		}
	}
	
	function collectCommission(address[] calldata _beneficiary, uint256[][] calldata _stakeID) external nonReentrant {
		harvest();
		for(uint256 i = 0; i< _beneficiary.length; ++i) {
			for(uint256 j = 0; j< _stakeID[i].length; ++j) {
                UserInfo storage user = userInfo[_beneficiary[i]][_stakeID[i][j]];
                payFee(user, _beneficiary[i]);
            }
		}
		collectVaultsCommission();
	}
	
	function collectCommissionAuto(address[] calldata _beneficiary) external nonReentrant {
		harvest();
		for(uint256 i = 0; i< _beneficiary.length; ++i) {
			
			uint256 _nrOfStakes = getNrOfStakes(_beneficiary[i]);
			
			for(uint256 j = 0; j < _nrOfStakes; ++j) {
                UserInfo storage user = userInfo[_beneficiary[i]][j];
                payFee(user, _beneficiary[i]);
            }
		}
		collectVaultsCommission();
	}

	function updateFees() external {
		uint256 _depositFee = IGovernor(IMasterChef(masterchef).owner()).depositFee();
		uint256 _fundingRate = IGovernor(IMasterChef(masterchef).owner()).fundingRate();

		require(_depositFee <= maxFee, "out of limit");
		require(_fundingRate <= maxFundingFee, "out of limit");

		depositFee = _depositFee;

		if(_fundingRate != fundingRate) {
			fundingRate = _fundingRate;
			lastFundingChangeTimestamp = block.timestamp;
		} 
	}

	function updateAddresses() external {
		masterchef = IMasterChef(IDTX(token).masterchefAddress());
		manageRewardsAddress = IGovernor(IMasterChef(masterchef).owner()).manageRewardsAddress();
		treasuryWallet = IGovernor(IMasterChef(masterchef).owner()).treasuryWallet();
		helperToken = IGovernor(IMasterChef(masterchef).owner()).helperToken();
	}
	
	function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external override returns (bytes4) {
        return this.onERC721Received.selector;
    }
    
    	/**
	 * option to withdraw wrongfully sent tokens(but requires change of the governing contract to do so)
	 * If you send wrong tokens to the contract address, consider them lost. Though there is possibility of recovery
	 */
	function withdrawStuckTokens(address _tokenAddress) external decentralizedVoting {
		IERC20(_tokenAddress).safeTransfer(treasuryWallet, IERC20(_tokenAddress).balanceOf(address(this)));
	}

    function withdrawNFT(address _address) external decentralizedVoting {
		nftContract.safeTransferFrom(address(this), _address, nftId);
	}

    function toUseNFT(bool _a) external decentralizedVoting {
		useNFT = _a;
	}

    function giveNFTApproval(address[] calldata _allowed, bool _permission) external decentralizedVoting {
        for(uint256 i = 0; i < _allowed.length; ++i) { 
		if(_allowed[i] != address(this)) {
			nftContract.setApprovalForAll(_allowed[i], _permission);
		}
        }
    }

	function collectVaultsCommission() public {
        IEmit(emitChef).withdraw(emissionsPoolId, vaultBalance);
		vaultBalance = 0;
		IERC20(stakeToken).safeTransfer(treasuryWallet, IERC20(stakeToken).balanceOf(address(this)));
	}
    
    function viewStakeEarnings(address _user, uint256 _stakeID) external view returns (uint256) {
		UserInfo storage _stake = userInfo[_user][_stakeID];
        uint256 _pending = _stake.amount * (virtualAccDtxPerShare() - _stake.debt) / 1e12 ;
        return _pending;
    }

    function viewUserTotalEarnings(address _user) external view returns (uint256) {
        UserInfo[] storage _stake = userInfo[_user];
        uint256 nrOfUserStakes = _stake.length;

		uint256 _totalPending = 0;
		
		for(uint256 i=0; i < nrOfUserStakes; ++i) {
			_totalPending+= _stake[i].amount * (virtualAccDtxPerShare() - _stake[i].debt) / 1e12 ;
		}
		
		return _totalPending;
    }
	//we want user deposit, we want total deposited, we want pending rewards, 
	function multiCall(address _user, uint256 _stakeID) external view returns(uint256, uint256, uint256, uint256) {
		UserInfo storage user = userInfo[_user][_stakeID];
		uint256 _pending = user.amount * (virtualAccDtxPerShare() - user.debt) / 1e12 ;
        EMISSIONS.UserView memory userView = IEmit(emitChef).getUserView(emissionsPoolId, address(this));
		uint256 _amount = userView.stakedAmount;
		return(user.amount, user.feesPaid, (_amount - vaultBalance), _pending);
	}

    /**
     * @return Returns total pending dtx rewards
     */
    function calculateTotalPendingDTXRewards() external view returns (uint256) {
        return(IMasterChef(masterchef).pendingDtx(poolID));
    }

	/**
     * Returns number of stakes for a user
     */
    function getNrOfStakes(address _user) public view returns (uint256) {
        return userInfo[_user].length;
    }

	//public lookup for UI
    function publicBalanceOf() public view returns (uint256) {
        uint256 amount = IMasterChef(masterchef).pendingDtx(poolID); 
        uint256 _credit = IMasterChef(masterchef).credit(address(this));
        return _credit + amount;
    }

	// With "Virtual harvest" for external calls
	function virtualAccDtxPerShare() public view returns (uint256) {
		uint256 _pending = IMasterChef(masterchef).pendingDtx(poolID);
		EMISSIONS.UserView memory userView = IEmit(emitChef).getUserView(emissionsPoolId, address(this));
		uint256 _amount = userView.stakedAmount;
		return (accDtxPerShare + _pending * 1e12  / (_amount - vaultBalance));
	}

    function payFee(UserInfo storage user, address _userAddress) private {
		uint256 _lastAction = user.lastAction;

		// Prevents charging new funding fee for the past (in case funding fee changes)
		// Before funding fee is changed, commissions must be manually collected
		if(lastFundingChangeTimestamp > _lastAction) {
			user.lastAction = lastFundingChangeTimestamp;
			_lastAction = lastFundingChangeTimestamp;
		}

        uint256 secondsSinceLastaction = block.timestamp - _lastAction;
				
		if(secondsSinceLastaction >= 3600  && fundingRate > 0) {
			user.lastAction = block.timestamp - (secondsSinceLastaction % 3600);
			
			uint256 commission = (block.timestamp - _lastAction) / 3600 * user.amount * fundingRate / 1000000;

			if(commission > user.amount * 2 / 10) {
				commission = user.amount * 2 / 10;
			}
			
		vaultBalance+= commission;

            user.feesPaid = user.feesPaid + commission;
			
			user.amount = user.amount - commission;
			
			emit CollectedFee(_userAddress, commission);
		}
	}


    /**
     * removes the stake
     */
    function _removeStake(address _staker, uint256 _stakeID) private {
        UserInfo[] storage stakes = userInfo[_staker];
        uint256 lastStakeID = stakes.length - 1;
        
        if(_stakeID != lastStakeID) {
            stakes[_stakeID] = stakes[lastStakeID];
        }
        
        stakes.pop();
    }
}

        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"error","name":"SafeERC20FailedOperation","inputs":[{"type":"address","name":"token","internalType":"address"}]},{"type":"event","name":"CollectedFee","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Deposit","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"debt","internalType":"uint256","indexed":false},{"type":"uint256","name":"depositFee","internalType":"uint256","indexed":false},{"type":"address","name":"referral","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"SelfHarvest","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"harvestAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Withdraw","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"stakeID","internalType":"uint256","indexed":false},{"type":"uint256","name":"harvestAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"accDtxPerShare","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"actuatorPoolId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"calculateTotalPendingDTXRewards","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"collectCommission","inputs":[{"type":"address[]","name":"_beneficiary","internalType":"address[]"},{"type":"uint256[][]","name":"_stakeID","internalType":"uint256[][]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"collectCommissionAuto","inputs":[{"type":"address[]","name":"_beneficiary","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"collectVaultsCommission","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deposit","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"address","name":"referral","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"depositFee","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"emergencyWithdraw","inputs":[{"type":"uint256","name":"_stakeID","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"emergencyWithdrawAll","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"emissionsPoolId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"emitChef","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"fundingRate","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getNrOfStakes","inputs":[{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"giveNFTApproval","inputs":[{"type":"address[]","name":"_allowed","internalType":"address[]"},{"type":"bool","name":"_permission","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"harvest","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"helperToken","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastCredit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastFundingChangeTimestamp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"manageRewardsAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IMasterChef"}],"name":"masterchef","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxFundingFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"multiCall","inputs":[{"type":"address","name":"_user","internalType":"address"},{"type":"uint256","name":"_stakeID","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC721"}],"name":"nftContract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nftId","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"onERC721Received","inputs":[{"type":"address","name":"operator","internalType":"address"},{"type":"address","name":"from","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"poolID","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"publicBalanceOf","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"referralPoints","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"referredBy","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"rewardToken","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"selfHarvest","inputs":[{"type":"address","name":"_userAddress","internalType":"address"},{"type":"uint256[]","name":"_stakeID","internalType":"uint256[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"stakeToken","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"toUseNFT","inputs":[{"type":"bool","name":"_a","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"token","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"treasuryWallet","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateAddresses","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateFees","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"useNFT","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"useRewards","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"debt","internalType":"uint256"},{"type":"uint256","name":"feesPaid","internalType":"uint256"},{"type":"uint256","name":"lastAction","internalType":"uint256"}],"name":"userInfo","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"vaultBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"viewStakeEarnings","inputs":[{"type":"address","name":"_user","internalType":"address"},{"type":"uint256","name":"_stakeID","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"viewUserTotalEarnings","inputs":[{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"virtualAccDtxPerShare","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[{"type":"uint256","name":"_stakeID","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawNFT","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawStuckTokens","inputs":[{"type":"address","name":"_tokenAddress","internalType":"address"}]}]
              

Contract Creation Code

Verify & Publish
0x60c06040525f6002819055600380546001600160a01b0319908116737cc0a0ca2f9346aceadd5110cfa15c4fa12f9251179091556004805482167332fb5663619a657839a80133994e45c5e5cdf4271790556005805490911673133f4205141d869a72724910331c0f0b7235df7b17905561010c6006556007805460ff19166001179055601181905560125534801562000097575f80fd5b5060015f557346814b3f18d90625b6e166bc2917bb64a635d79760a08190526010600c55733e79130ab714e97ee73f86a56a2427bb1a51989660805260035460405163095ea7b360e01b81526001600160a01b0390911660048201525f19602482015263095ea7b3906044016020604051808303815f875af115801562000120573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200014691906200014d565b5062000175565b5f602082840312156200015e575f80fd5b815180151581146200016e575f80fd5b9392505050565b60805160a0516135d6620001e45f395f8181610445015281816108c4015281816109af01528181610c0201528181610cc501528181610d3a01528181611201015281816112ec015281816113bf015281816116e901526117b101525f8181610653015261268801526135d65ff3fe608060405234801561000f575f80fd5b50600436106102cb575f3560e01c80638129fc1c1161017b578063d56d229d116100e4578063ed9c8b001161009e578063f7c618c111610079578063f7c618c114610628578063fb1db2781461063b578063fc0c546a1461064e578063fc9fc6c714610675575f80fd5b8063ed9c8b0014610603578063f3a3af571461060c578063f6acc21014610615575f80fd5b8063d56d229d14610590578063dd191719146105a3578063e26db6fc146105ab578063e2d983dd146105b3578063e5ea69ff146105bc578063eb72d4f1146105e4575f80fd5b8063b206c11a11610135578063b206c11a1461053d578063b719c61f14610550578063c6bc518214610558578063c6c211e914610561578063cb63bc8b14610574578063cb9637281461057d575f80fd5b80638129fc1c146104e15780638d934485146104e957806390b3a908146104f257806393e29dd8146104fa57806399827f731461050d578063a90f8e9a14610515575f80fd5b8063444d73d3116102375780635312ea8e116101f157806367a52793116101cc57806367a527931461049f578063681e0522146104a85780636d675029146104bb5780636e553f65146104ce575f80fd5b80635312ea8e14610467578063607214d31461047a578063615427ec14610482575f80fd5b8063444d73d3146103fc5780634626402b146104145780634641257d1461042757806348fcc2f01461042f5780634b9bc1971461043857806351ed6a3014610440575f80fd5b80632e1a7d4d116102885780632e1a7d4d14610387578063339cfc1c1461039a578063390a556c146103a25780633cabbbf7146103cd5780633dbc1752146103e057806341d3c84c146103f3575f80fd5b806301f59d16146102cf5780630bf6cc08146102eb5780630f51d02c146102f4578063150b7a0214610307578063157157861461033f57806321ce919d14610354575b5f80fd5b6102d86109c481565b6040519081526020015b60405180910390f35b6102d860025481565b6102d8610302366004613063565b61067d565b61032661031536600461308d565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020016102e2565b61035261034d366004613131565b6106f6565b005b610367610362366004613063565b6107b6565b6040805194855260208501939093529183015260608201526080016102e2565b610352610395366004613153565b6107f8565b610352610c35565b6008546103b5906001600160a01b031681565b6040516001600160a01b0390911681526020016102e2565b6003546103b5906001600160a01b031681565b6103526103ee3660046131b2565b610d63565b6102d860125481565b6007546103b59061010090046001600160a01b031681565b600f546103b5906001600160a01b031681565b610352610e9f565b6102d860135481565b6102d8611043565b6103b57f000000000000000000000000000000000000000000000000000000000000000081565b610352610475366004613153565b61113d565b6102d86113f1565b60075461048f9060ff1681565b60405190151581526020016102e2565b6102d860115481565b6103526104b63660046131f1565b611465565b6102d86104c9366004613258565b6115b9565b6103526104dc366004613273565b611671565b610352611b18565b6102d8600c5481565b6102d8600a81565b6103526105083660046132a1565b611c5d565b610352611dec565b6103b5610523366004613258565b600a6020525f90815260409020546001600160a01b031681565b61035261054b3660046132f4565b611f53565b6102d86122dd565b6102d860065481565b61036761056f366004613063565b61240f565b6102d8600d5481565b61035261058b366004613258565b61252e565b6005546103b5906001600160a01b031681565b610352612655565b610352612686565b6102d86103e881565b6102d86105ca366004613258565b6001600160a01b03165f9081526009602052604090205490565b6102d86105f2366004613258565b600b6020525f908152604090205481565b6102d8600e5481565b6102d860105481565b610352610623366004613258565b6129c6565b6004546103b5906001600160a01b031681565b6001546103b5906001600160a01b031681565b6103b57f000000000000000000000000000000000000000000000000000000000000000081565b610352612ad7565b6001600160a01b0382165f9081526009602052604081208054829190849081106106a9576106a9613345565b905f5260205f20906004020190505f64e8d4a5100082600101546106cb6122dd565b6106d5919061336d565b83546106e19190613380565b6106eb91906133ab565b925050505b92915050565b60015f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610746573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061076a91906133be565b6001600160a01b0316336001600160a01b0316146107a35760405162461bcd60e51b815260040161079a906133d9565b60405180910390fd5b6007805460ff1916911515919091179055565b6009602052815f5260405f2081815481106107cf575f80fd5b5f9182526020909120600490910201805460018201546002830154600390930154919450925084565b60025f54036108195760405162461bcd60e51b815260040161079a90613410565b60025f55610825610e9f565b335f9081526009602052604090205481106108755760405162461bcd60e51b815260206004820152601060248201526f1a5b9d985b1a59081cdd185ad948125160821b604482015260640161079a565b335f90815260096020526040812080548390811061089557610895613345565b905f5260205f20906004020190506108ad8133612d17565b6040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610911573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109359190613447565b6003548354604051630441a3e760e41b8152600a600482015260248101919091529192506001600160a01b03169063441a3e70906044015f604051808303815f87803b158015610983575f80fd5b505af1158015610995573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201525f92507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691506370a0823190602401602060405180830381865afa1580156109fd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a219190613447565b90505f610a2e838361336d565b90505f64e8d4a510008560010154600e54610a49919061336d565b8654610a559190613380565b610a5f91906133ab565b9050610a6b3387612e73565b60015460085460405163cc58a6bb60e01b81526001600160a01b0391821660048201526024810184905291169063cc58a6bb906044015f604051808303815f87803b158015610ab8575f80fd5b505af1158015610aca573d5f803e3d5ffd5b50506008546040516340c10f1960e01b8152336004820152602481018590526001600160a01b0390911692506340c10f1991506044015f604051808303815f87803b158015610b17575f80fd5b505af1158015610b29573d5f803e3d5ffd5b5050335f908152600a60205260409020546001600160a01b0316159150610ba9905057335f908152600b602052604081208054839290610b6a90849061345e565b9091555050335f908152600a60209081526040808320546001600160a01b03168352600b90915281208054839290610ba390849061345e565b90915550505b80601054610bb7919061336d565b601055604080518781526020810183905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a2610c296001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163384612f46565b505060015f5550505050565b600354600254604051630441a3e760e41b8152600a600482015260248101919091526001600160a01b039091169063441a3e70906044015f604051808303815f87803b158015610c83575f80fd5b505af1158015610c95573d5f803e3d5ffd5b50505f6002555050600f546040516370a0823160e01b8152306004820152610d61916001600160a01b03908116917f0000000000000000000000000000000000000000000000000000000000000000909116906370a0823190602401602060405180830381865afa158015610d0c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d309190613447565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190612f46565b565b60025f5403610d845760405162461bcd60e51b815260040161079a90613410565b60025f55610d90610e9f565b5f5b81811015610e8e575f610dc5848484818110610db057610db0613345565b90506020020160208101906105ca9190613258565b90505f5b81811015610e7b575f60095f878787818110610de757610de7613345565b9050602002016020810190610dfc9190613258565b6001600160a01b03166001600160a01b031681526020019081526020015f208281548110610e2c57610e2c613345565b905f5260205f2090600402019050610e6a81878787818110610e5057610e50613345565b9050602002016020810190610e659190613258565b612d17565b50610e7481613471565b9050610dc9565b505080610e8790613471565b9050610d92565b50610e97610c35565b505060015f55565b600154600c546040516328f582d360e11b81526001600160a01b03909216916351eb05a691610ed49160040190815260200190565b5f604051808303815f87803b158015610eeb575f80fd5b505af1158015610efd573d5f803e3d5ffd5b50506001546040516301aba89b60e71b81523060048201525f93506001600160a01b03909116915063d5d44d8090602401602060405180830381865afa158015610f49573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f6d9190613447565b90505f60105482610f7e919061336d565b601083905560035460405163900ea58760e01b8152600a60048201523060248201529192505f916001600160a01b039091169063900ea5879060440160a060405180830381865afa158015610fd5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ff99190613489565b60208101516002549192509061100f908261336d565b61101e8464e8d4a51000613380565b61102891906133ab565b600e5f828254611038919061345e565b909155505050505050565b600154600c5460405163b6ec056160e01b81525f9283926001600160a01b039091169163b6ec05619161107c9160040190815260200190565b602060405180830381865afa158015611097573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110bb9190613447565b6001546040516301aba89b60e71b81523060048201529192505f916001600160a01b039091169063d5d44d8090602401602060405180830381865afa158015611106573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112a9190613447565b9050611136828261345e565b9250505090565b60025f540361115e5760405162461bcd60e51b815260040161079a90613410565b60025f9081553381526009602052604090205481106111b25760405162461bcd60e51b815260206004820152601060248201526f1a5b9d985b1a59081cdd185ad948125160821b604482015260640161079a565b335f9081526009602052604081208054839081106111d2576111d2613345565b905f5260205f20906004020190506111ea8133612d17565b6040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561124e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112729190613447565b6003548354604051630441a3e760e41b8152600a600482015260248101919091529192506001600160a01b03169063441a3e70906044015f604051808303815f87803b1580156112c0575f80fd5b505af11580156112d2573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201525f92507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691506370a0823190602401602060405180830381865afa15801561133a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061135e9190613447565b90505f61136b838361336d565b90506113773386612e73565b604080518681526020810183905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a26113e66001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383612f46565b505060015f55505050565b600154600c5460405163b6ec056160e01b815260048101919091525f916001600160a01b03169063b6ec056190602401602060405180830381865afa15801561143c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114609190613447565b905090565b60025f54036114865760405162461bcd60e51b815260040161079a90613410565b60025f55611492610e9f565b5f5b838110156115a6575f5b8383838181106114b0576114b0613345565b90506020028101906114c29190613503565b9050811015611595575f60095f8888868181106114e1576114e1613345565b90506020020160208101906114f69190613258565b6001600160a01b03166001600160a01b031681526020019081526020015f2085858581811061152757611527613345565b90506020028101906115399190613503565b8481811061154957611549613345565b905060200201358154811061156057611560613345565b905f5260205f209060040201905061158481888886818110610e5057610e50613345565b5061158e81613471565b905061149e565b5061159f81613471565b9050611494565b506115af610c35565b505060015f555050565b6001600160a01b0381165f908152600960205260408120805482805b828110156116685764e8d4a510008482815481106115f5576115f5613345565b905f5260205f2090600402016001015461160d6122dd565b611617919061336d565b85838154811061162957611629613345565b905f5260205f2090600402015f01546116429190613380565b61164c91906133ab565b611656908361345e565b915061166181613471565b90506115d5565b50949350505050565b60025f54036116925760405162461bcd60e51b815260040161079a90613410565b60025f55816116d45760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a5908185b5bdd5b9d60921b604482015260640161079a565b6116dc610e9f565b6117116001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333085612faa565b335f908152600a60205260409020546001600160a01b031615801561173f57506001600160a01b0381163314155b1561176c57335f908152600a6020526040902080546001600160a01b0319166001600160a01b0383161790555b5f6011545f146117da57612710601154846117879190613380565b61179191906133ab565b905061179d818461336d565b600f549093506117da906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683612f46565b600e5460075460ff16156118d6576005546006546040516331a9108f60e11b815260048101919091525f916001600160a01b031690636352211e90602401602060405180830381865afa158015611833573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185791906133be565b90506001600160a01b03811630146118d457600554600654604051632142170760e11b81526001600160a01b03848116600483015230602483015260448201929092529116906342842e0e906064015f604051808303815f87803b1580156118bd575f80fd5b505af11580156118cf573d5f803e3d5ffd5b505050505b505b60035460405163900ea58760e01b8152600a60048201523060248201525f916001600160a01b03169063900ea5879060440160a060405180830381865afa158015611923573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119479190613489565b6020810151600354604051638dbdbe6d60e01b8152600a600482015260248101899052736494d2569b81e5a6164212e641331a530a150c3b604482015292935090916001600160a01b0390911690638dbdbe6d906064015f604051808303815f87803b1580156119b5575f80fd5b505af11580156119c7573d5f803e3d5ffd5b505060035460405163900ea58760e01b8152600a60048201523060248201526001600160a01b03909116925063900ea587915060440160a060405180830381865afa158015611a18573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a3c9190613489565b60208101519092505f611a4f838361336d565b335f81815260096020908152604080832081516080810183528681528084018c81528184018e8152426060808501918252855460018082018855968a52888a20955160049091029095019485559251948401949094555160028301559151600390910155848452600a8352928190205481518e81529283018b90529082018b90529394506001600160a01b03909316927fede963da60ce3b657af455d654d08ff95549f13a4acb219b68756f68755e28e3910160405180910390a3505060015f55505050505050565b60035460405163900ea58760e01b8152600a60048201523060248201525f916001600160a01b03169063900ea5879060440160a060405180830381865afa158015611b65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b899190613489565b60208101519091508015611bdf5760405162461bcd60e51b815260206004820152601b60248201527f6f6e6c7920696e697469616c697a6174696f6e20616c6c6f7765640000000000604482015260640161079a565b600354604051638dbdbe6d60e01b8152600a600482015260016024820152736494d2569b81e5a6164212e641331a530a150c3b60448201526001600160a01b0390911690638dbdbe6d906064015f604051808303815f87803b158015611c43575f80fd5b505af1158015611c55573d5f803e3d5ffd5b505050505050565b60015f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cad573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cd191906133be565b6001600160a01b0316336001600160a01b031614611d015760405162461bcd60e51b815260040161079a906133d9565b5f5b82811015611de65730848483818110611d1e57611d1e613345565b9050602002016020810190611d339190613258565b6001600160a01b031614611dd6576005546001600160a01b031663a22cb465858584818110611d6457611d64613345565b9050602002016020810190611d799190613258565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015284151560248201526044015f604051808303815f87803b158015611dbf575f80fd5b505af1158015611dd1573d5f803e3d5ffd5b505050505b611ddf81613471565b9050611d03565b50505050565b600354604051638dbdbe6d60e01b8152600a60048201525f6024820152736494d2569b81e5a6164212e641331a530a150c3b60448201526001600160a01b0390911690638dbdbe6d906064015f604051808303815f87803b158015611e4f575f80fd5b505af1158015611e61573d5f803e3d5ffd5b5050600480546007546040516370a0823160e01b815230938101939093526001600160a01b03918216945063a9059cbb93506101009004169083906370a0823190602401602060405180830381865afa158015611ec0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ee49190613447565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015611f2c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f509190613549565b50565b60025f5403611f745760405162461bcd60e51b815260040161079a90613410565b60025f9081556001600160a01b038416815260096020526040902054811115611fd65760405162461bcd60e51b81526020600482015260146024820152731a5b98dbdc9c9958dd0814dd185ad9481b1a5cdd60621b604482015260640161079a565b6001600160a01b0383165f908152600960205260409020611ff5610e9f565b5f805b838110156121355761203f8386868481811061201657612016613345565b905060200201358154811061202d5761202d613345565b905f5260205f20906004020187612d17565b64e8d4a510008386868481811061205857612058613345565b905060200201358154811061206f5761206f613345565b905f5260205f20906004020160010154600e5461208c919061336d565b8487878581811061209f5761209f613345565b90506020020135815481106120b6576120b6613345565b905f5260205f2090600402015f01546120cf9190613380565b6120d991906133ab565b6120e3908361345e565b9150600e54838686848181106120fb576120fb613345565b905060200201358154811061211257612112613345565b5f91825260209091206001600490920201015561212e81613471565b9050611ff8565b5060015460085460405163cc58a6bb60e01b81526001600160a01b0391821660048201526024810184905291169063cc58a6bb906044015f604051808303815f87803b158015612183575f80fd5b505af1158015612195573d5f803e3d5ffd5b50506008546040516340c10f1960e01b81526001600160a01b0389811660048301526024820186905290911692506340c10f1991506044015f604051808303815f87803b1580156121e4575f80fd5b505af11580156121f6573d5f803e3d5ffd5b505050506001600160a01b038581165f908152600a60205260409020541615612283576001600160a01b0385165f908152600b60205260408120805483929061224090849061345e565b90915550506001600160a01b038086165f908152600a60209081526040808320549093168252600b9052908120805483929061227d90849061345e565b90915550505b80601054612291919061336d565b6010556040518181526001600160a01b038616907f72d95b85c523e9b0e60084e1da9ca8f9b7e4c2fe225b74d1e13de98b4242df809060200160405180910390a2505060015f55505050565b600154600c5460405163b6ec056160e01b81525f9283926001600160a01b039091169163b6ec0561916123169160040190815260200190565b602060405180830381865afa158015612331573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123559190613447565b60035460405163900ea58760e01b8152600a60048201523060248201529192505f916001600160a01b039091169063900ea5879060440160a060405180830381865afa1580156123a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123cb9190613489565b6020810151600254919250906123e1908261336d565b6123f08464e8d4a51000613380565b6123fa91906133ab565b600e54612407919061345e565b935050505090565b6001600160a01b0382165f908152600960205260408120805482918291829182918790811061244057612440613345565b905f5260205f20906004020190505f64e8d4a5100082600101546124626122dd565b61246c919061336d565b83546124789190613380565b61248291906133ab565b60035460405163900ea58760e01b8152600a60048201523060248201529192505f916001600160a01b039091169063900ea5879060440160a060405180830381865afa1580156124d4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124f89190613489565b90505f81602001519050835f0154846002015460025483612519919061336d565b919c909b509099509297509195505050505050565b60015f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561257e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125a291906133be565b6001600160a01b0316336001600160a01b0316146125d25760405162461bcd60e51b815260040161079a906133d9565b600f546040516370a0823160e01b8152306004820152611f50916001600160a01b0390811691908416906370a0823190602401602060405180830381865afa158015612620573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126449190613447565b6001600160a01b0384169190612f46565b335f908152600960205260409020545b8015611f50578061267581613564565b9150506126818161113d565b612665565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166340c34b586040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126e2573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061270691906133be565b600180546001600160a01b0319166001600160a01b0392909216918217905560408051638da5cb5b60e01b81529051638da5cb5b916004808201926020929091908290030181865afa15801561275e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061278291906133be565b6001600160a01b031663444d73d36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127e191906133be565b60078054610100600160a81b0319166101006001600160a01b039384160217905560015460408051638da5cb5b60e01b815290519190921691638da5cb5b9160048083019260209291908290030181865afa158015612842573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061286691906133be565b6001600160a01b0316634626402b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128a1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128c591906133be565b600f80546001600160a01b0319166001600160a01b0392831617905560015460408051638da5cb5b60e01b815290519190921691638da5cb5b9160048083019260209291908290030181865afa158015612921573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061294591906133be565b6001600160a01b031663390a556c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612980573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129a491906133be565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b60015f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a16573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a3a91906133be565b6001600160a01b0316336001600160a01b031614612a6a5760405162461bcd60e51b815260040161079a906133d9565b600554600654604051632142170760e11b81523060048201526001600160a01b03848116602483015260448201929092529116906342842e0e906064015f604051808303815f87803b158015612abe575f80fd5b505af1158015612ad0573d5f803e3d5ffd5b5050505050565b60015460408051638da5cb5b60e01b815290515f926001600160a01b031691638da5cb5b9160048083019260209291908290030181865afa158015612b1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b4291906133be565b6001600160a01b03166367a527936040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b7d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ba19190613447565b90505f60015f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bf4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c1891906133be565b6001600160a01b03166341d3c84c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c53573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c779190613447565b90506109c4821115612cba5760405162461bcd60e51b815260206004820152600c60248201526b1bdd5d081bd9881b1a5b5a5d60a21b604482015260640161079a565b6103e8811115612cfb5760405162461bcd60e51b815260206004820152600c60248201526b1bdd5d081bd9881b1a5b5a5d60a21b604482015260640161079a565b60118290556012548114612d13576012819055426013555b5050565b6003820154601354811015612d325750601354600383018190555b5f612d3d824261336d565b9050610e108110158015612d5257505f601254115b15611de657612d63610e1082613579565b612d6d904261336d565b600385015560125484545f91620f424091610e10612d8b874261336d565b612d9591906133ab565b612d9f9190613380565b612da99190613380565b612db391906133ab565b8554909150600a90612dc6906002613380565b612dd091906133ab565b811115612df4578454600a90612de7906002613380565b612df191906133ab565b90505b8060025f828254612e05919061345e565b90915550506002850154612e1a90829061345e565b60028601558454612e2c90829061336d565b85556040518181526001600160a01b038516907f5a7af898dfbf9d56c66a7883a2e9229f5c9ff2484d9525f2c80cff815e2328279060200160405180910390a25050505050565b6001600160a01b0382165f9081526009602052604081208054909190612e9b9060019061336d565b9050808314612f0657818181548110612eb657612eb6613345565b905f5260205f209060040201828481548110612ed457612ed4613345565b5f9182526020909120825460049092020190815560018083015490820155600280830154908201556003918201549101555b81805480612f1657612f1661358c565b5f8281526020812060045f1990930192830201818155600181018290556002810182905560030155905550505050565b6040516001600160a01b03838116602483015260448201839052612fa591859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612fe3565b505050565b6040516001600160a01b038481166024830152838116604483015260648201839052611de69186918216906323b872dd90608401612f73565b5f8060205f8451602086015f885af180613002576040513d5f823e3d81fd5b50505f513d91508115613019578060011415613026565b6001600160a01b0384163b155b15611de657604051635274afe760e01b81526001600160a01b038516600482015260240161079a565b6001600160a01b0381168114611f50575f80fd5b5f8060408385031215613074575f80fd5b823561307f8161304f565b946020939093013593505050565b5f805f805f608086880312156130a1575f80fd5b85356130ac8161304f565b945060208601356130bc8161304f565b935060408601359250606086013567ffffffffffffffff808211156130df575f80fd5b818801915088601f8301126130f2575f80fd5b813581811115613100575f80fd5b896020828501011115613111575f80fd5b9699959850939650602001949392505050565b8015158114611f50575f80fd5b5f60208284031215613141575f80fd5b813561314c81613124565b9392505050565b5f60208284031215613163575f80fd5b5035919050565b5f8083601f84011261317a575f80fd5b50813567ffffffffffffffff811115613191575f80fd5b6020830191508360208260051b85010111156131ab575f80fd5b9250929050565b5f80602083850312156131c3575f80fd5b823567ffffffffffffffff8111156131d9575f80fd5b6131e58582860161316a565b90969095509350505050565b5f805f8060408587031215613204575f80fd5b843567ffffffffffffffff8082111561321b575f80fd5b6132278883890161316a565b9096509450602087013591508082111561323f575f80fd5b5061324c8782880161316a565b95989497509550505050565b5f60208284031215613268575f80fd5b813561314c8161304f565b5f8060408385031215613284575f80fd5b8235915060208301356132968161304f565b809150509250929050565b5f805f604084860312156132b3575f80fd5b833567ffffffffffffffff8111156132c9575f80fd5b6132d58682870161316a565b90945092505060208401356132e981613124565b809150509250925092565b5f805f60408486031215613306575f80fd5b83356133118161304f565b9250602084013567ffffffffffffffff81111561332c575f80fd5b6133388682870161316a565b9497909650939450505050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b818103818111156106f0576106f0613359565b80820281158282048414176106f0576106f0613359565b634e487b7160e01b5f52601260045260245ffd5b5f826133b9576133b9613397565b500490565b5f602082840312156133ce575f80fd5b815161314c8161304f565b6020808252601a908201527f446563656e7472616c697a656420566f74696e67204f6e6c7921000000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b5f60208284031215613457575f80fd5b5051919050565b808201808211156106f0576106f0613359565b5f6001820161348257613482613359565b5060010190565b5f60a08284031215613499575f80fd5b60405160a0810181811067ffffffffffffffff821117156134c857634e487b7160e01b5f52604160045260245ffd5b806040525082518152602083015160208201526040830151604082015260608301516060820152608083015160808201528091505092915050565b5f808335601e19843603018112613518575f80fd5b83018035915067ffffffffffffffff821115613532575f80fd5b6020019150600581901b36038213156131ab575f80fd5b5f60208284031215613559575f80fd5b815161314c81613124565b5f8161357257613572613359565b505f190190565b5f8261358757613587613397565b500690565b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220c69c509b180501707e10b3decc46a5757323a78d41f26ac8dcdd4524021f267f64736f6c63430008140033

Deployed ByteCode

0x608060405234801561000f575f80fd5b50600436106102cb575f3560e01c80638129fc1c1161017b578063d56d229d116100e4578063ed9c8b001161009e578063f7c618c111610079578063f7c618c114610628578063fb1db2781461063b578063fc0c546a1461064e578063fc9fc6c714610675575f80fd5b8063ed9c8b0014610603578063f3a3af571461060c578063f6acc21014610615575f80fd5b8063d56d229d14610590578063dd191719146105a3578063e26db6fc146105ab578063e2d983dd146105b3578063e5ea69ff146105bc578063eb72d4f1146105e4575f80fd5b8063b206c11a11610135578063b206c11a1461053d578063b719c61f14610550578063c6bc518214610558578063c6c211e914610561578063cb63bc8b14610574578063cb9637281461057d575f80fd5b80638129fc1c146104e15780638d934485146104e957806390b3a908146104f257806393e29dd8146104fa57806399827f731461050d578063a90f8e9a14610515575f80fd5b8063444d73d3116102375780635312ea8e116101f157806367a52793116101cc57806367a527931461049f578063681e0522146104a85780636d675029146104bb5780636e553f65146104ce575f80fd5b80635312ea8e14610467578063607214d31461047a578063615427ec14610482575f80fd5b8063444d73d3146103fc5780634626402b146104145780634641257d1461042757806348fcc2f01461042f5780634b9bc1971461043857806351ed6a3014610440575f80fd5b80632e1a7d4d116102885780632e1a7d4d14610387578063339cfc1c1461039a578063390a556c146103a25780633cabbbf7146103cd5780633dbc1752146103e057806341d3c84c146103f3575f80fd5b806301f59d16146102cf5780630bf6cc08146102eb5780630f51d02c146102f4578063150b7a0214610307578063157157861461033f57806321ce919d14610354575b5f80fd5b6102d86109c481565b6040519081526020015b60405180910390f35b6102d860025481565b6102d8610302366004613063565b61067d565b61032661031536600461308d565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020016102e2565b61035261034d366004613131565b6106f6565b005b610367610362366004613063565b6107b6565b6040805194855260208501939093529183015260608201526080016102e2565b610352610395366004613153565b6107f8565b610352610c35565b6008546103b5906001600160a01b031681565b6040516001600160a01b0390911681526020016102e2565b6003546103b5906001600160a01b031681565b6103526103ee3660046131b2565b610d63565b6102d860125481565b6007546103b59061010090046001600160a01b031681565b600f546103b5906001600160a01b031681565b610352610e9f565b6102d860135481565b6102d8611043565b6103b57f00000000000000000000000046814b3f18d90625b6e166bc2917bb64a635d79781565b610352610475366004613153565b61113d565b6102d86113f1565b60075461048f9060ff1681565b60405190151581526020016102e2565b6102d860115481565b6103526104b63660046131f1565b611465565b6102d86104c9366004613258565b6115b9565b6103526104dc366004613273565b611671565b610352611b18565b6102d8600c5481565b6102d8600a81565b6103526105083660046132a1565b611c5d565b610352611dec565b6103b5610523366004613258565b600a6020525f90815260409020546001600160a01b031681565b61035261054b3660046132f4565b611f53565b6102d86122dd565b6102d860065481565b61036761056f366004613063565b61240f565b6102d8600d5481565b61035261058b366004613258565b61252e565b6005546103b5906001600160a01b031681565b610352612655565b610352612686565b6102d86103e881565b6102d86105ca366004613258565b6001600160a01b03165f9081526009602052604090205490565b6102d86105f2366004613258565b600b6020525f908152604090205481565b6102d8600e5481565b6102d860105481565b610352610623366004613258565b6129c6565b6004546103b5906001600160a01b031681565b6001546103b5906001600160a01b031681565b6103b57f0000000000000000000000003e79130ab714e97ee73f86a56a2427bb1a51989681565b610352612ad7565b6001600160a01b0382165f9081526009602052604081208054829190849081106106a9576106a9613345565b905f5260205f20906004020190505f64e8d4a5100082600101546106cb6122dd565b6106d5919061336d565b83546106e19190613380565b6106eb91906133ab565b925050505b92915050565b60015f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610746573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061076a91906133be565b6001600160a01b0316336001600160a01b0316146107a35760405162461bcd60e51b815260040161079a906133d9565b60405180910390fd5b6007805460ff1916911515919091179055565b6009602052815f5260405f2081815481106107cf575f80fd5b5f9182526020909120600490910201805460018201546002830154600390930154919450925084565b60025f54036108195760405162461bcd60e51b815260040161079a90613410565b60025f55610825610e9f565b335f9081526009602052604090205481106108755760405162461bcd60e51b815260206004820152601060248201526f1a5b9d985b1a59081cdd185ad948125160821b604482015260640161079a565b335f90815260096020526040812080548390811061089557610895613345565b905f5260205f20906004020190506108ad8133612d17565b6040516370a0823160e01b81523060048201525f907f00000000000000000000000046814b3f18d90625b6e166bc2917bb64a635d7976001600160a01b0316906370a0823190602401602060405180830381865afa158015610911573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109359190613447565b6003548354604051630441a3e760e41b8152600a600482015260248101919091529192506001600160a01b03169063441a3e70906044015f604051808303815f87803b158015610983575f80fd5b505af1158015610995573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201525f92507f00000000000000000000000046814b3f18d90625b6e166bc2917bb64a635d7976001600160a01b031691506370a0823190602401602060405180830381865afa1580156109fd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a219190613447565b90505f610a2e838361336d565b90505f64e8d4a510008560010154600e54610a49919061336d565b8654610a559190613380565b610a5f91906133ab565b9050610a6b3387612e73565b60015460085460405163cc58a6bb60e01b81526001600160a01b0391821660048201526024810184905291169063cc58a6bb906044015f604051808303815f87803b158015610ab8575f80fd5b505af1158015610aca573d5f803e3d5ffd5b50506008546040516340c10f1960e01b8152336004820152602481018590526001600160a01b0390911692506340c10f1991506044015f604051808303815f87803b158015610b17575f80fd5b505af1158015610b29573d5f803e3d5ffd5b5050335f908152600a60205260409020546001600160a01b0316159150610ba9905057335f908152600b602052604081208054839290610b6a90849061345e565b9091555050335f908152600a60209081526040808320546001600160a01b03168352600b90915281208054839290610ba390849061345e565b90915550505b80601054610bb7919061336d565b601055604080518781526020810183905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a2610c296001600160a01b037f00000000000000000000000046814b3f18d90625b6e166bc2917bb64a635d797163384612f46565b505060015f5550505050565b600354600254604051630441a3e760e41b8152600a600482015260248101919091526001600160a01b039091169063441a3e70906044015f604051808303815f87803b158015610c83575f80fd5b505af1158015610c95573d5f803e3d5ffd5b50505f6002555050600f546040516370a0823160e01b8152306004820152610d61916001600160a01b03908116917f00000000000000000000000046814b3f18d90625b6e166bc2917bb64a635d797909116906370a0823190602401602060405180830381865afa158015610d0c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d309190613447565b6001600160a01b037f00000000000000000000000046814b3f18d90625b6e166bc2917bb64a635d797169190612f46565b565b60025f5403610d845760405162461bcd60e51b815260040161079a90613410565b60025f55610d90610e9f565b5f5b81811015610e8e575f610dc5848484818110610db057610db0613345565b90506020020160208101906105ca9190613258565b90505f5b81811015610e7b575f60095f878787818110610de757610de7613345565b9050602002016020810190610dfc9190613258565b6001600160a01b03166001600160a01b031681526020019081526020015f208281548110610e2c57610e2c613345565b905f5260205f2090600402019050610e6a81878787818110610e5057610e50613345565b9050602002016020810190610e659190613258565b612d17565b50610e7481613471565b9050610dc9565b505080610e8790613471565b9050610d92565b50610e97610c35565b505060015f55565b600154600c546040516328f582d360e11b81526001600160a01b03909216916351eb05a691610ed49160040190815260200190565b5f604051808303815f87803b158015610eeb575f80fd5b505af1158015610efd573d5f803e3d5ffd5b50506001546040516301aba89b60e71b81523060048201525f93506001600160a01b03909116915063d5d44d8090602401602060405180830381865afa158015610f49573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f6d9190613447565b90505f60105482610f7e919061336d565b601083905560035460405163900ea58760e01b8152600a60048201523060248201529192505f916001600160a01b039091169063900ea5879060440160a060405180830381865afa158015610fd5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ff99190613489565b60208101516002549192509061100f908261336d565b61101e8464e8d4a51000613380565b61102891906133ab565b600e5f828254611038919061345e565b909155505050505050565b600154600c5460405163b6ec056160e01b81525f9283926001600160a01b039091169163b6ec05619161107c9160040190815260200190565b602060405180830381865afa158015611097573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110bb9190613447565b6001546040516301aba89b60e71b81523060048201529192505f916001600160a01b039091169063d5d44d8090602401602060405180830381865afa158015611106573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112a9190613447565b9050611136828261345e565b9250505090565b60025f540361115e5760405162461bcd60e51b815260040161079a90613410565b60025f9081553381526009602052604090205481106111b25760405162461bcd60e51b815260206004820152601060248201526f1a5b9d985b1a59081cdd185ad948125160821b604482015260640161079a565b335f9081526009602052604081208054839081106111d2576111d2613345565b905f5260205f20906004020190506111ea8133612d17565b6040516370a0823160e01b81523060048201525f907f00000000000000000000000046814b3f18d90625b6e166bc2917bb64a635d7976001600160a01b0316906370a0823190602401602060405180830381865afa15801561124e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112729190613447565b6003548354604051630441a3e760e41b8152600a600482015260248101919091529192506001600160a01b03169063441a3e70906044015f604051808303815f87803b1580156112c0575f80fd5b505af11580156112d2573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201525f92507f00000000000000000000000046814b3f18d90625b6e166bc2917bb64a635d7976001600160a01b031691506370a0823190602401602060405180830381865afa15801561133a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061135e9190613447565b90505f61136b838361336d565b90506113773386612e73565b604080518681526020810183905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a26113e66001600160a01b037f00000000000000000000000046814b3f18d90625b6e166bc2917bb64a635d797163383612f46565b505060015f55505050565b600154600c5460405163b6ec056160e01b815260048101919091525f916001600160a01b03169063b6ec056190602401602060405180830381865afa15801561143c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114609190613447565b905090565b60025f54036114865760405162461bcd60e51b815260040161079a90613410565b60025f55611492610e9f565b5f5b838110156115a6575f5b8383838181106114b0576114b0613345565b90506020028101906114c29190613503565b9050811015611595575f60095f8888868181106114e1576114e1613345565b90506020020160208101906114f69190613258565b6001600160a01b03166001600160a01b031681526020019081526020015f2085858581811061152757611527613345565b90506020028101906115399190613503565b8481811061154957611549613345565b905060200201358154811061156057611560613345565b905f5260205f209060040201905061158481888886818110610e5057610e50613345565b5061158e81613471565b905061149e565b5061159f81613471565b9050611494565b506115af610c35565b505060015f555050565b6001600160a01b0381165f908152600960205260408120805482805b828110156116685764e8d4a510008482815481106115f5576115f5613345565b905f5260205f2090600402016001015461160d6122dd565b611617919061336d565b85838154811061162957611629613345565b905f5260205f2090600402015f01546116429190613380565b61164c91906133ab565b611656908361345e565b915061166181613471565b90506115d5565b50949350505050565b60025f54036116925760405162461bcd60e51b815260040161079a90613410565b60025f55816116d45760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a5908185b5bdd5b9d60921b604482015260640161079a565b6116dc610e9f565b6117116001600160a01b037f00000000000000000000000046814b3f18d90625b6e166bc2917bb64a635d79716333085612faa565b335f908152600a60205260409020546001600160a01b031615801561173f57506001600160a01b0381163314155b1561176c57335f908152600a6020526040902080546001600160a01b0319166001600160a01b0383161790555b5f6011545f146117da57612710601154846117879190613380565b61179191906133ab565b905061179d818461336d565b600f549093506117da906001600160a01b037f00000000000000000000000046814b3f18d90625b6e166bc2917bb64a635d7978116911683612f46565b600e5460075460ff16156118d6576005546006546040516331a9108f60e11b815260048101919091525f916001600160a01b031690636352211e90602401602060405180830381865afa158015611833573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185791906133be565b90506001600160a01b03811630146118d457600554600654604051632142170760e11b81526001600160a01b03848116600483015230602483015260448201929092529116906342842e0e906064015f604051808303815f87803b1580156118bd575f80fd5b505af11580156118cf573d5f803e3d5ffd5b505050505b505b60035460405163900ea58760e01b8152600a60048201523060248201525f916001600160a01b03169063900ea5879060440160a060405180830381865afa158015611923573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119479190613489565b6020810151600354604051638dbdbe6d60e01b8152600a600482015260248101899052736494d2569b81e5a6164212e641331a530a150c3b604482015292935090916001600160a01b0390911690638dbdbe6d906064015f604051808303815f87803b1580156119b5575f80fd5b505af11580156119c7573d5f803e3d5ffd5b505060035460405163900ea58760e01b8152600a60048201523060248201526001600160a01b03909116925063900ea587915060440160a060405180830381865afa158015611a18573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a3c9190613489565b60208101519092505f611a4f838361336d565b335f81815260096020908152604080832081516080810183528681528084018c81528184018e8152426060808501918252855460018082018855968a52888a20955160049091029095019485559251948401949094555160028301559151600390910155848452600a8352928190205481518e81529283018b90529082018b90529394506001600160a01b03909316927fede963da60ce3b657af455d654d08ff95549f13a4acb219b68756f68755e28e3910160405180910390a3505060015f55505050505050565b60035460405163900ea58760e01b8152600a60048201523060248201525f916001600160a01b03169063900ea5879060440160a060405180830381865afa158015611b65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b899190613489565b60208101519091508015611bdf5760405162461bcd60e51b815260206004820152601b60248201527f6f6e6c7920696e697469616c697a6174696f6e20616c6c6f7765640000000000604482015260640161079a565b600354604051638dbdbe6d60e01b8152600a600482015260016024820152736494d2569b81e5a6164212e641331a530a150c3b60448201526001600160a01b0390911690638dbdbe6d906064015f604051808303815f87803b158015611c43575f80fd5b505af1158015611c55573d5f803e3d5ffd5b505050505050565b60015f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cad573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cd191906133be565b6001600160a01b0316336001600160a01b031614611d015760405162461bcd60e51b815260040161079a906133d9565b5f5b82811015611de65730848483818110611d1e57611d1e613345565b9050602002016020810190611d339190613258565b6001600160a01b031614611dd6576005546001600160a01b031663a22cb465858584818110611d6457611d64613345565b9050602002016020810190611d799190613258565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015284151560248201526044015f604051808303815f87803b158015611dbf575f80fd5b505af1158015611dd1573d5f803e3d5ffd5b505050505b611ddf81613471565b9050611d03565b50505050565b600354604051638dbdbe6d60e01b8152600a60048201525f6024820152736494d2569b81e5a6164212e641331a530a150c3b60448201526001600160a01b0390911690638dbdbe6d906064015f604051808303815f87803b158015611e4f575f80fd5b505af1158015611e61573d5f803e3d5ffd5b5050600480546007546040516370a0823160e01b815230938101939093526001600160a01b03918216945063a9059cbb93506101009004169083906370a0823190602401602060405180830381865afa158015611ec0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ee49190613447565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015611f2c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f509190613549565b50565b60025f5403611f745760405162461bcd60e51b815260040161079a90613410565b60025f9081556001600160a01b038416815260096020526040902054811115611fd65760405162461bcd60e51b81526020600482015260146024820152731a5b98dbdc9c9958dd0814dd185ad9481b1a5cdd60621b604482015260640161079a565b6001600160a01b0383165f908152600960205260409020611ff5610e9f565b5f805b838110156121355761203f8386868481811061201657612016613345565b905060200201358154811061202d5761202d613345565b905f5260205f20906004020187612d17565b64e8d4a510008386868481811061205857612058613345565b905060200201358154811061206f5761206f613345565b905f5260205f20906004020160010154600e5461208c919061336d565b8487878581811061209f5761209f613345565b90506020020135815481106120b6576120b6613345565b905f5260205f2090600402015f01546120cf9190613380565b6120d991906133ab565b6120e3908361345e565b9150600e54838686848181106120fb576120fb613345565b905060200201358154811061211257612112613345565b5f91825260209091206001600490920201015561212e81613471565b9050611ff8565b5060015460085460405163cc58a6bb60e01b81526001600160a01b0391821660048201526024810184905291169063cc58a6bb906044015f604051808303815f87803b158015612183575f80fd5b505af1158015612195573d5f803e3d5ffd5b50506008546040516340c10f1960e01b81526001600160a01b0389811660048301526024820186905290911692506340c10f1991506044015f604051808303815f87803b1580156121e4575f80fd5b505af11580156121f6573d5f803e3d5ffd5b505050506001600160a01b038581165f908152600a60205260409020541615612283576001600160a01b0385165f908152600b60205260408120805483929061224090849061345e565b90915550506001600160a01b038086165f908152600a60209081526040808320549093168252600b9052908120805483929061227d90849061345e565b90915550505b80601054612291919061336d565b6010556040518181526001600160a01b038616907f72d95b85c523e9b0e60084e1da9ca8f9b7e4c2fe225b74d1e13de98b4242df809060200160405180910390a2505060015f55505050565b600154600c5460405163b6ec056160e01b81525f9283926001600160a01b039091169163b6ec0561916123169160040190815260200190565b602060405180830381865afa158015612331573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123559190613447565b60035460405163900ea58760e01b8152600a60048201523060248201529192505f916001600160a01b039091169063900ea5879060440160a060405180830381865afa1580156123a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123cb9190613489565b6020810151600254919250906123e1908261336d565b6123f08464e8d4a51000613380565b6123fa91906133ab565b600e54612407919061345e565b935050505090565b6001600160a01b0382165f908152600960205260408120805482918291829182918790811061244057612440613345565b905f5260205f20906004020190505f64e8d4a5100082600101546124626122dd565b61246c919061336d565b83546124789190613380565b61248291906133ab565b60035460405163900ea58760e01b8152600a60048201523060248201529192505f916001600160a01b039091169063900ea5879060440160a060405180830381865afa1580156124d4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124f89190613489565b90505f81602001519050835f0154846002015460025483612519919061336d565b919c909b509099509297509195505050505050565b60015f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561257e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125a291906133be565b6001600160a01b0316336001600160a01b0316146125d25760405162461bcd60e51b815260040161079a906133d9565b600f546040516370a0823160e01b8152306004820152611f50916001600160a01b0390811691908416906370a0823190602401602060405180830381865afa158015612620573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126449190613447565b6001600160a01b0384169190612f46565b335f908152600960205260409020545b8015611f50578061267581613564565b9150506126818161113d565b612665565b7f0000000000000000000000003e79130ab714e97ee73f86a56a2427bb1a5198966001600160a01b03166340c34b586040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126e2573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061270691906133be565b600180546001600160a01b0319166001600160a01b0392909216918217905560408051638da5cb5b60e01b81529051638da5cb5b916004808201926020929091908290030181865afa15801561275e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061278291906133be565b6001600160a01b031663444d73d36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127e191906133be565b60078054610100600160a81b0319166101006001600160a01b039384160217905560015460408051638da5cb5b60e01b815290519190921691638da5cb5b9160048083019260209291908290030181865afa158015612842573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061286691906133be565b6001600160a01b0316634626402b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128a1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128c591906133be565b600f80546001600160a01b0319166001600160a01b0392831617905560015460408051638da5cb5b60e01b815290519190921691638da5cb5b9160048083019260209291908290030181865afa158015612921573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061294591906133be565b6001600160a01b031663390a556c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612980573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129a491906133be565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b60015f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a16573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a3a91906133be565b6001600160a01b0316336001600160a01b031614612a6a5760405162461bcd60e51b815260040161079a906133d9565b600554600654604051632142170760e11b81523060048201526001600160a01b03848116602483015260448201929092529116906342842e0e906064015f604051808303815f87803b158015612abe575f80fd5b505af1158015612ad0573d5f803e3d5ffd5b5050505050565b60015460408051638da5cb5b60e01b815290515f926001600160a01b031691638da5cb5b9160048083019260209291908290030181865afa158015612b1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b4291906133be565b6001600160a01b03166367a527936040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b7d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ba19190613447565b90505f60015f9054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bf4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c1891906133be565b6001600160a01b03166341d3c84c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c53573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c779190613447565b90506109c4821115612cba5760405162461bcd60e51b815260206004820152600c60248201526b1bdd5d081bd9881b1a5b5a5d60a21b604482015260640161079a565b6103e8811115612cfb5760405162461bcd60e51b815260206004820152600c60248201526b1bdd5d081bd9881b1a5b5a5d60a21b604482015260640161079a565b60118290556012548114612d13576012819055426013555b5050565b6003820154601354811015612d325750601354600383018190555b5f612d3d824261336d565b9050610e108110158015612d5257505f601254115b15611de657612d63610e1082613579565b612d6d904261336d565b600385015560125484545f91620f424091610e10612d8b874261336d565b612d9591906133ab565b612d9f9190613380565b612da99190613380565b612db391906133ab565b8554909150600a90612dc6906002613380565b612dd091906133ab565b811115612df4578454600a90612de7906002613380565b612df191906133ab565b90505b8060025f828254612e05919061345e565b90915550506002850154612e1a90829061345e565b60028601558454612e2c90829061336d565b85556040518181526001600160a01b038516907f5a7af898dfbf9d56c66a7883a2e9229f5c9ff2484d9525f2c80cff815e2328279060200160405180910390a25050505050565b6001600160a01b0382165f9081526009602052604081208054909190612e9b9060019061336d565b9050808314612f0657818181548110612eb657612eb6613345565b905f5260205f209060040201828481548110612ed457612ed4613345565b5f9182526020909120825460049092020190815560018083015490820155600280830154908201556003918201549101555b81805480612f1657612f1661358c565b5f8281526020812060045f1990930192830201818155600181018290556002810182905560030155905550505050565b6040516001600160a01b03838116602483015260448201839052612fa591859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612fe3565b505050565b6040516001600160a01b038481166024830152838116604483015260648201839052611de69186918216906323b872dd90608401612f73565b5f8060205f8451602086015f885af180613002576040513d5f823e3d81fd5b50505f513d91508115613019578060011415613026565b6001600160a01b0384163b155b15611de657604051635274afe760e01b81526001600160a01b038516600482015260240161079a565b6001600160a01b0381168114611f50575f80fd5b5f8060408385031215613074575f80fd5b823561307f8161304f565b946020939093013593505050565b5f805f805f608086880312156130a1575f80fd5b85356130ac8161304f565b945060208601356130bc8161304f565b935060408601359250606086013567ffffffffffffffff808211156130df575f80fd5b818801915088601f8301126130f2575f80fd5b813581811115613100575f80fd5b896020828501011115613111575f80fd5b9699959850939650602001949392505050565b8015158114611f50575f80fd5b5f60208284031215613141575f80fd5b813561314c81613124565b9392505050565b5f60208284031215613163575f80fd5b5035919050565b5f8083601f84011261317a575f80fd5b50813567ffffffffffffffff811115613191575f80fd5b6020830191508360208260051b85010111156131ab575f80fd5b9250929050565b5f80602083850312156131c3575f80fd5b823567ffffffffffffffff8111156131d9575f80fd5b6131e58582860161316a565b90969095509350505050565b5f805f8060408587031215613204575f80fd5b843567ffffffffffffffff8082111561321b575f80fd5b6132278883890161316a565b9096509450602087013591508082111561323f575f80fd5b5061324c8782880161316a565b95989497509550505050565b5f60208284031215613268575f80fd5b813561314c8161304f565b5f8060408385031215613284575f80fd5b8235915060208301356132968161304f565b809150509250929050565b5f805f604084860312156132b3575f80fd5b833567ffffffffffffffff8111156132c9575f80fd5b6132d58682870161316a565b90945092505060208401356132e981613124565b809150509250925092565b5f805f60408486031215613306575f80fd5b83356133118161304f565b9250602084013567ffffffffffffffff81111561332c575f80fd5b6133388682870161316a565b9497909650939450505050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b818103818111156106f0576106f0613359565b80820281158282048414176106f0576106f0613359565b634e487b7160e01b5f52601260045260245ffd5b5f826133b9576133b9613397565b500490565b5f602082840312156133ce575f80fd5b815161314c8161304f565b6020808252601a908201527f446563656e7472616c697a656420566f74696e67204f6e6c7921000000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b5f60208284031215613457575f80fd5b5051919050565b808201808211156106f0576106f0613359565b5f6001820161348257613482613359565b5060010190565b5f60a08284031215613499575f80fd5b60405160a0810181811067ffffffffffffffff821117156134c857634e487b7160e01b5f52604160045260245ffd5b806040525082518152602083015160208201526040830151604082015260608301516060820152608083015160808201528091505092915050565b5f808335601e19843603018112613518575f80fd5b83018035915067ffffffffffffffff821115613532575f80fd5b6020019150600581901b36038213156131ab575f80fd5b5f60208284031215613559575f80fd5b815161314c81613124565b5f8161357257613572613359565b505f190190565b5f8261358757613587613397565b500690565b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220c69c509b180501707e10b3decc46a5757323a78d41f26ac8dcdd4524021f267f64736f6c63430008140033