Contract Address Details

0x566E5Ae3DA86ECd8DB68BC9b2a5Ed3225C6DEd42

Contract Name
RealDogePunksPool
Creator
0xece369–fbe31e at 0x0b103f–edfba2
Balance
0 Doge
Tokens
Fetching tokens...
Transactions
752 Transactions
Transfers
388 Transfers
Gas Used
55,342,731
Last Balance Update
28798620
Contract name:
RealDogePunksPool




Optimization enabled
false
Compiler version
v0.8.7+commit.e28d00a7




EVM Version
default




Verified at
2022-09-02T17:03:35.238748Z

Constructor Arguments

000000000000000000000000d38b22794b308a2e55808a13d1e6a80c4be94fd50000000000000000000000007b4328c127b85369d9f82ca0503b000d09cf9180000000000000000000000000ece369f372f55baebfe37d5a27a70e145bfbe31e00000000000000000000000000000000000000000000000000000000000004d20000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000384

Arg [0] (address) : 0xd38b22794b308a2e55808a13d1e6a80c4be94fd5
Arg [1] (address) : 0x7b4328c127b85369d9f82ca0503b000d09cf9180
Arg [2] (address) : 0xece369f372f55baebfe37d5a27a70e145bfbe31e
Arg [3] (uint256) : 1234
Arg [4] (uint256) : 1000000000000000000
Arg [5] (uint256) : 900

              

Contract source code

// File: @openzeppelin/contracts/utils/Context.sol


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

pragma solidity ^0.8.0;

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

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

// File: @openzeppelin/contracts/access/Ownable.sol


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

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 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: @openzeppelin/contracts/utils/math/SafeMath.sol


// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

// File: @openzeppelin/contracts/security/ReentrancyGuard.sol


// OpenZeppelin Contracts v4.4.1 (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: @openzeppelin/contracts/token/ERC20/IERC20.sol


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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * 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[EIP 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: @openzeppelin/contracts/token/ERC721/IERC721.sol


// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


/**
 * @dev Required interface of an ERC721 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 ERC721 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: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * 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 caller.
     *
     * 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: contracts/pool.sol


pragma solidity >=0.8.4;







contract RealDogePunksPool is IERC721Receiver, ReentrancyGuard {
    using SafeMath for uint256;

    IERC721 public nftToken;
    IERC20 public erc20Token;

    address public daoAdmin;
    uint256 public tokensPerBlock;
    uint256 public floor;
    uint256 public fee; 

    struct stake {
        uint256 tokenId;
        uint256 stakedFromBlock;
        address owner;
    }

    // TokenID => Stake
    mapping(uint256 => stake) public receipt;

    event NftStaked(address indexed staker, uint256 tokenId, uint256 blockNumber);
    event NftUnStaked(address indexed staker, uint256 tokenId, uint256 blockNumber);
    event StakePayout(address indexed staker, uint256 tokenId, uint256 stakeAmount, uint256 fromBlock, uint256 toBlock);
    event StakeRewardUpdated(uint256 rewardPerBlock);
    event FloorUpdated(uint256 floor);

    modifier onlyStaker(uint256 tokenId) {
        // require that this contract has the NFT
        require(nftToken.ownerOf(tokenId) == address(this), "onlyStaker: Contract is not owner of this NFT");

        // require that this token is staked
        require(receipt[tokenId].stakedFromBlock != 0, "onlyStaker: Token is not staked");

        // require that msg.sender is the owner of this nft
        require(receipt[tokenId].owner == msg.sender, "onlyStaker: Caller is not NFT stake owner");

        _;
    }

    modifier requireTimeElapsed(uint256 tokenId) {
        // require that some time has elapsed (IE you can not stake and unstake in the same block)
        require(
            receipt[tokenId].stakedFromBlock < block.number,
            "requireTimeElapsed: Can not stake/unStake/harvest in same block"
        );
        _;
    }

    modifier onlyDao() {
        require(msg.sender == daoAdmin, "reclaimTokens: Caller is not the DAO");
        _;
    }

    constructor(
        IERC721 _nftToken,
        IERC20 _erc20Token,
        address _daoAdmin,
        uint256 _tokensPerBlock,
        uint256 _floor,
        uint256 _fee
    ) {
        nftToken = _nftToken;
        erc20Token = _erc20Token;
        daoAdmin = _daoAdmin;
        tokensPerBlock = _tokensPerBlock;
        floor = _floor;
        fee = _fee;

        emit StakeRewardUpdated(tokensPerBlock);
    }

    /**
     * Always returns `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address,
        address,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }

    //User must give this contract permission to take ownership of it.

    function buyNFT(uint256 tokenId) public payable nonReentrant returns (bool) {

    require(msg.value >= floor, "price error");
        return _buyNFT(tokenId);
    }

    function _buyNFT(uint256 tokenId) internal returns (bool) {

        require(msg.value >= floor, "price error");

        // delete stake record, effectively unstaking it
        delete receipt[tokenId];

        // return token
        nftToken.safeTransferFrom(address(this), msg.sender, tokenId);

        emit NftUnStaked(msg.sender, tokenId, block.number);

        return true;
    }


    function reclaimTokens() external onlyDao {
        erc20Token.transfer(daoAdmin, erc20Token.balanceOf(address(this)));
    }

    function withdraw() external onlyDao {
    require(payable(msg.sender).send(address(this).balance));
    }

    function updateFloor(uint256 _floor) external onlyDao {
        floor = _floor;
        emit FloorUpdated(floor);
    }

    function updateFee(uint256 _fee) external onlyDao {
        fee = _fee;
    }

   function sellNFT(uint256 tokenId) public payable nonReentrant returns (bool) {

//    require(msg.value >= floor, "price error");
        return _sellNFT(tokenId);
    }

    function _sellNFT(uint256 tokenId) internal returns (bool) {
    
    // check pool balance
    uint256 fee1 = floor - (floor * fee / 10000);
    require ( address(this).balance > (fee1) , "NFT Pool can not buy now");

        // take possession of the NFT
        nftToken.safeTransferFrom(msg.sender, address(this), tokenId);

        // check that this contract is the owner
        require(nftToken.ownerOf(tokenId) == address(this), "Stake: Failed to take possession of NFT");

        // nftpool payment send
        payable(msg.sender).transfer(fee1);

        // start the staking from this block.
        receipt[tokenId].tokenId = tokenId;
        receipt[tokenId].stakedFromBlock = block.number;
        receipt[tokenId].owner = msg.sender;

        emit NftStaked(msg.sender, tokenId, block.number);

        return true;
    }

    function _payoutStake(uint256 tokenId) internal {
        /* NOTE : Must be called from non-reentrant function to be safe!*/

        // double check that the receipt exists and we're not staking from block 0
        require(receipt[tokenId].stakedFromBlock > 0, "_payoutStake: Can not stake from block 0");

        // earned amount is difference between the stake start block, current block multiplied by stake amount
        uint256 timeStaked = _getTimeStaked(tokenId).sub(1); // don't pay for the tx block of withdrawl
        uint256 payout = timeStaked.mul(tokensPerBlock);

        // If contract does not have enough tokens to pay out, return the NFT without payment
        // This prevent a NFT being locked in the contract when empty
        if (erc20Token.balanceOf(address(this)) < payout) {
            emit StakePayout(msg.sender, tokenId, 0, receipt[tokenId].stakedFromBlock, block.number);
            return;
        }

        // payout stake
        erc20Token.transfer(receipt[tokenId].owner, payout);

        emit StakePayout(msg.sender, tokenId, payout, receipt[tokenId].stakedFromBlock, block.number);
    }

    function _getTimeStaked(uint256 tokenId) internal view returns (uint256) {
        if (receipt[tokenId].stakedFromBlock == 0) {
            return 0;
        }

        return block.number.sub(receipt[tokenId].stakedFromBlock);
    }


    function getBalance() public view returns (uint256) {
    return address(this).balance;
    }
    
    receive() external payable {
    }

    fallback() external payable {
    }
    
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_nftToken","internalType":"contract IERC721"},{"type":"address","name":"_erc20Token","internalType":"contract IERC20"},{"type":"address","name":"_daoAdmin","internalType":"address"},{"type":"uint256","name":"_tokensPerBlock","internalType":"uint256"},{"type":"uint256","name":"_floor","internalType":"uint256"},{"type":"uint256","name":"_fee","internalType":"uint256"}]},{"type":"event","name":"FloorUpdated","inputs":[{"type":"uint256","name":"floor","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NftStaked","inputs":[{"type":"address","name":"staker","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false},{"type":"uint256","name":"blockNumber","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NftUnStaked","inputs":[{"type":"address","name":"staker","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false},{"type":"uint256","name":"blockNumber","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"StakePayout","inputs":[{"type":"address","name":"staker","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false},{"type":"uint256","name":"stakeAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"fromBlock","internalType":"uint256","indexed":false},{"type":"uint256","name":"toBlock","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"StakeRewardUpdated","inputs":[{"type":"uint256","name":"rewardPerBlock","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"fallback","stateMutability":"payable"},{"type":"function","stateMutability":"payable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"buyNFT","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"daoAdmin","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"erc20Token","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"fee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"floor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC721"}],"name":"nftToken","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"onERC721Received","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"bytes","name":"","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"stakedFromBlock","internalType":"uint256"},{"type":"address","name":"owner","internalType":"address"}],"name":"receipt","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"reclaimTokens","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"sellNFT","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokensPerBlock","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateFee","inputs":[{"type":"uint256","name":"_fee","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateFloor","inputs":[{"type":"uint256","name":"_floor","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[]},{"type":"receive","stateMutability":"payable"}]
            

Contract Creation Code

0x60806040523480156200001157600080fd5b5060405162001b7638038062001b768339818101604052810190620000379190620001ba565b600160008190555085600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260048190555081600581905550806006819055507f8299c7e9ca8ced629afb284155951141eded288b72d7d6b56cb24fbf999a9dfc6004546040516200014a919062000267565b60405180910390a150505050505062000357565b6000815190506200016f81620002ef565b92915050565b600081519050620001868162000309565b92915050565b6000815190506200019d8162000323565b92915050565b600081519050620001b4816200033d565b92915050565b60008060008060008060c08789031215620001da57620001d9620002ea565b5b6000620001ea89828a016200018c565b9650506020620001fd89828a0162000175565b95505060406200021089828a016200015e565b94505060606200022389828a01620001a3565b93505060806200023689828a01620001a3565b92505060a06200024989828a01620001a3565b9150509295509295509295565b6200026181620002e0565b82525050565b60006020820190506200027e600083018462000256565b92915050565b60006200029182620002c0565b9050919050565b6000620002a58262000284565b9050919050565b6000620002b98262000284565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600080fd5b620002fa8162000284565b81146200030657600080fd5b50565b620003148162000298565b81146200032057600080fd5b50565b6200032e81620002ac565b81146200033a57600080fd5b50565b6200034881620002e0565b81146200035457600080fd5b50565b61180f80620003676000396000f3fe6080604052600436106100ec5760003560e01c806351ed82881161008a578063b7b856aa11610059578063b7b856aa146102cf578063d06fcba8146102f8578063ddca3f4314610323578063ee9cdfb31461034e576100f3565b806351ed82881461020c5780638a13eea71461023c5780639012c4a814610267578063a2aa433714610290576100f3565b80631a1cb01f116100c65780631a1cb01f146101885780633c54caa5146101b35780633ccfd60b146101ca57806340695363146101e1576100f3565b806302de4387146100f557806312065fe014610120578063150b7a021461014b576100f3565b366100f357005b005b34801561010157600080fd5b5061010a61037e565b60405161011791906111a5565b60405180910390f35b34801561012c57600080fd5b506101356103a4565b604051610142919061132c565b60405180910390f35b34801561015757600080fd5b50610172600480360381019061016d9190610f92565b6103ac565b60405161017f919061123b565b60405180910390f35b34801561019457600080fd5b5061019d6103c0565b6040516101aa919061132c565b60405180910390f35b3480156101bf57600080fd5b506101c86103c6565b005b3480156101d657600080fd5b506101df6105d4565b005b3480156101ed57600080fd5b506101f66106a4565b604051610203919061132c565b60405180910390f35b61022660048036038101906102219190611042565b6106aa565b6040516102339190611220565b60405180910390f35b34801561024857600080fd5b50610251610757565b60405161025e9190611256565b60405180910390f35b34801561027357600080fd5b5061028e60048036038101906102899190611042565b61077d565b005b34801561029c57600080fd5b506102b760048036038101906102b29190611042565b610817565b6040516102c693929190611370565b60405180910390f35b3480156102db57600080fd5b506102f660048036038101906102f19190611042565b610861565b005b34801561030457600080fd5b5061030d610934565b60405161031a9190611271565b60405180910390f35b34801561032f57600080fd5b5061033861095a565b604051610345919061132c565b60405180910390f35b61036860048036038101906103639190611042565b610960565b6040516103759190611220565b60405180910390f35b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600047905090565b600063150b7a0260e01b9050949350505050565b60045481565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610456576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044d906112cc565b60405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161051291906111a5565b60206040518083038186803b15801561052a57600080fd5b505afa15801561053e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610562919061106f565b6040518363ffffffff1660e01b815260040161057f9291906111f7565b602060405180830381600087803b15801561059957600080fd5b505af11580156105ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d19190611015565b50565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610664576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065b906112cc565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f193505050506106a257600080fd5b565b60055481565b6000600260005414156106f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e99061130c565b60405180910390fd5b600260008190555060055434101561073f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610736906112ac565b60405180910390fd5b610748826109c8565b90506001600081905550919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461080d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610804906112cc565b60405180910390fd5b8060068190555050565b60076020528060005260406000206000915090508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e8906112cc565b60405180910390fd5b806005819055507fa7a696c280d1b8a49f1f616aaed7fc30ca8ffad2b5de0fa2ca17fbdde2ba940c600554604051610929919061132c565b60405180910390a150565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60065481565b6000600260005414156109a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099f9061130c565b60405180910390fd5b60026000819055506109b982610b46565b90506001600081905550919050565b6000600554341015610a0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a06906112ac565b60405180910390fd5b6007600083815260200190815260200160002060008082016000905560018201600090556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3033856040518463ffffffff1660e01b8152600401610abb939291906111c0565b600060405180830381600087803b158015610ad557600080fd5b505af1158015610ae9573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff167f32bc6caf9c29ce36f00f0386a4015fd281d5d4058d348d1a684a24a05c9b324d8343604051610b35929190611347565b60405180910390a260019050919050565b600080612710600654600554610b5c919061143f565b610b66919061140e565b600554610b739190611499565b9050804711610bb7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bae906112ec565b60405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3330866040518463ffffffff1660e01b8152600401610c16939291906111c0565b600060405180830381600087803b158015610c3057600080fd5b505af1158015610c44573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e856040518263ffffffff1660e01b8152600401610cba919061132c565b60206040518083038186803b158015610cd257600080fd5b505afa158015610ce6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0a9190610f65565b73ffffffffffffffffffffffffffffffffffffffff1614610d60576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d579061128c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610da6573d6000803e3d6000fd5b50826007600085815260200190815260200160002060000181905550436007600085815260200190815260200160002060010181905550336007600085815260200190815260200160002060020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f2209f5ab1e50b2a6cab82d8f63686a6991f8d51072e1c8c6e752570697c29c468443604051610e7a929190611347565b60405180910390a26001915050919050565b6000610e9f610e9a846113cc565b6113a7565b905082815260208101848484011115610ebb57610eba61165b565b5b610ec6848285611589565b509392505050565b600081359050610edd81611794565b92915050565b600081519050610ef281611794565b92915050565b600081519050610f07816117ab565b92915050565b600082601f830112610f2257610f21611656565b5b8135610f32848260208601610e8c565b91505092915050565b600081359050610f4a816117c2565b92915050565b600081519050610f5f816117c2565b92915050565b600060208284031215610f7b57610f7a611665565b5b6000610f8984828501610ee3565b91505092915050565b60008060008060808587031215610fac57610fab611665565b5b6000610fba87828801610ece565b9450506020610fcb87828801610ece565b9350506040610fdc87828801610f3b565b925050606085013567ffffffffffffffff811115610ffd57610ffc611660565b5b61100987828801610f0d565b91505092959194509250565b60006020828403121561102b5761102a611665565b5b600061103984828501610ef8565b91505092915050565b60006020828403121561105857611057611665565b5b600061106684828501610f3b565b91505092915050565b60006020828403121561108557611084611665565b5b600061109384828501610f50565b91505092915050565b6110a5816114cd565b82525050565b6110b4816114df565b82525050565b6110c3816114eb565b82525050565b6110d281611541565b82525050565b6110e181611553565b82525050565b60006110f46027836113fd565b91506110ff8261167b565b604082019050919050565b6000611117600b836113fd565b9150611122826116ca565b602082019050919050565b600061113a6024836113fd565b9150611145826116f3565b604082019050919050565b600061115d6018836113fd565b915061116882611742565b602082019050919050565b6000611180601f836113fd565b915061118b8261176b565b602082019050919050565b61119f81611537565b82525050565b60006020820190506111ba600083018461109c565b92915050565b60006060820190506111d5600083018661109c565b6111e2602083018561109c565b6111ef6040830184611196565b949350505050565b600060408201905061120c600083018561109c565b6112196020830184611196565b9392505050565b600060208201905061123560008301846110ab565b92915050565b600060208201905061125060008301846110ba565b92915050565b600060208201905061126b60008301846110c9565b92915050565b600060208201905061128660008301846110d8565b92915050565b600060208201905081810360008301526112a5816110e7565b9050919050565b600060208201905081810360008301526112c58161110a565b9050919050565b600060208201905081810360008301526112e58161112d565b9050919050565b6000602082019050818103600083015261130581611150565b9050919050565b6000602082019050818103600083015261132581611173565b9050919050565b60006020820190506113416000830184611196565b92915050565b600060408201905061135c6000830185611196565b6113696020830184611196565b9392505050565b60006060820190506113856000830186611196565b6113926020830185611196565b61139f604083018461109c565b949350505050565b60006113b16113c2565b90506113bd8282611598565b919050565b6000604051905090565b600067ffffffffffffffff8211156113e7576113e6611627565b5b6113f08261166a565b9050602081019050919050565b600082825260208201905092915050565b600061141982611537565b915061142483611537565b925082611434576114336115f8565b5b828204905092915050565b600061144a82611537565b915061145583611537565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561148e5761148d6115c9565b5b828202905092915050565b60006114a482611537565b91506114af83611537565b9250828210156114c2576114c16115c9565b5b828203905092915050565b60006114d882611517565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061154c82611565565b9050919050565b600061155e82611565565b9050919050565b600061157082611577565b9050919050565b600061158282611517565b9050919050565b82818337600083830152505050565b6115a18261166a565b810181811067ffffffffffffffff821117156115c0576115bf611627565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f5374616b653a204661696c656420746f2074616b6520706f7373657373696f6e60008201527f206f66204e465400000000000000000000000000000000000000000000000000602082015250565b7f7072696365206572726f72000000000000000000000000000000000000000000600082015250565b7f7265636c61696d546f6b656e733a2043616c6c6572206973206e6f742074686560008201527f2044414f00000000000000000000000000000000000000000000000000000000602082015250565b7f4e465420506f6f6c2063616e206e6f7420627579206e6f770000000000000000600082015250565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b61179d816114cd565b81146117a857600080fd5b50565b6117b4816114df565b81146117bf57600080fd5b50565b6117cb81611537565b81146117d657600080fd5b5056fea2646970667358221220d06cde7c429bea0bbd6e4ad33253fa2f4e17ba0dab124713f97ebd77d01567a864736f6c63430008070033000000000000000000000000d38b22794b308a2e55808a13d1e6a80c4be94fd50000000000000000000000007b4328c127b85369d9f82ca0503b000d09cf9180000000000000000000000000ece369f372f55baebfe37d5a27a70e145bfbe31e00000000000000000000000000000000000000000000000000000000000004d20000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000384

Deployed ByteCode

0x6080604052600436106100ec5760003560e01c806351ed82881161008a578063b7b856aa11610059578063b7b856aa146102cf578063d06fcba8146102f8578063ddca3f4314610323578063ee9cdfb31461034e576100f3565b806351ed82881461020c5780638a13eea71461023c5780639012c4a814610267578063a2aa433714610290576100f3565b80631a1cb01f116100c65780631a1cb01f146101885780633c54caa5146101b35780633ccfd60b146101ca57806340695363146101e1576100f3565b806302de4387146100f557806312065fe014610120578063150b7a021461014b576100f3565b366100f357005b005b34801561010157600080fd5b5061010a61037e565b60405161011791906111a5565b60405180910390f35b34801561012c57600080fd5b506101356103a4565b604051610142919061132c565b60405180910390f35b34801561015757600080fd5b50610172600480360381019061016d9190610f92565b6103ac565b60405161017f919061123b565b60405180910390f35b34801561019457600080fd5b5061019d6103c0565b6040516101aa919061132c565b60405180910390f35b3480156101bf57600080fd5b506101c86103c6565b005b3480156101d657600080fd5b506101df6105d4565b005b3480156101ed57600080fd5b506101f66106a4565b604051610203919061132c565b60405180910390f35b61022660048036038101906102219190611042565b6106aa565b6040516102339190611220565b60405180910390f35b34801561024857600080fd5b50610251610757565b60405161025e9190611256565b60405180910390f35b34801561027357600080fd5b5061028e60048036038101906102899190611042565b61077d565b005b34801561029c57600080fd5b506102b760048036038101906102b29190611042565b610817565b6040516102c693929190611370565b60405180910390f35b3480156102db57600080fd5b506102f660048036038101906102f19190611042565b610861565b005b34801561030457600080fd5b5061030d610934565b60405161031a9190611271565b60405180910390f35b34801561032f57600080fd5b5061033861095a565b604051610345919061132c565b60405180910390f35b61036860048036038101906103639190611042565b610960565b6040516103759190611220565b60405180910390f35b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600047905090565b600063150b7a0260e01b9050949350505050565b60045481565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610456576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044d906112cc565b60405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161051291906111a5565b60206040518083038186803b15801561052a57600080fd5b505afa15801561053e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610562919061106f565b6040518363ffffffff1660e01b815260040161057f9291906111f7565b602060405180830381600087803b15801561059957600080fd5b505af11580156105ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d19190611015565b50565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610664576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065b906112cc565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f193505050506106a257600080fd5b565b60055481565b6000600260005414156106f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e99061130c565b60405180910390fd5b600260008190555060055434101561073f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610736906112ac565b60405180910390fd5b610748826109c8565b90506001600081905550919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461080d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610804906112cc565b60405180910390fd5b8060068190555050565b60076020528060005260406000206000915090508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e8906112cc565b60405180910390fd5b806005819055507fa7a696c280d1b8a49f1f616aaed7fc30ca8ffad2b5de0fa2ca17fbdde2ba940c600554604051610929919061132c565b60405180910390a150565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60065481565b6000600260005414156109a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099f9061130c565b60405180910390fd5b60026000819055506109b982610b46565b90506001600081905550919050565b6000600554341015610a0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a06906112ac565b60405180910390fd5b6007600083815260200190815260200160002060008082016000905560018201600090556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3033856040518463ffffffff1660e01b8152600401610abb939291906111c0565b600060405180830381600087803b158015610ad557600080fd5b505af1158015610ae9573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff167f32bc6caf9c29ce36f00f0386a4015fd281d5d4058d348d1a684a24a05c9b324d8343604051610b35929190611347565b60405180910390a260019050919050565b600080612710600654600554610b5c919061143f565b610b66919061140e565b600554610b739190611499565b9050804711610bb7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bae906112ec565b60405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3330866040518463ffffffff1660e01b8152600401610c16939291906111c0565b600060405180830381600087803b158015610c3057600080fd5b505af1158015610c44573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e856040518263ffffffff1660e01b8152600401610cba919061132c565b60206040518083038186803b158015610cd257600080fd5b505afa158015610ce6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0a9190610f65565b73ffffffffffffffffffffffffffffffffffffffff1614610d60576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d579061128c565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610da6573d6000803e3d6000fd5b50826007600085815260200190815260200160002060000181905550436007600085815260200190815260200160002060010181905550336007600085815260200190815260200160002060020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f2209f5ab1e50b2a6cab82d8f63686a6991f8d51072e1c8c6e752570697c29c468443604051610e7a929190611347565b60405180910390a26001915050919050565b6000610e9f610e9a846113cc565b6113a7565b905082815260208101848484011115610ebb57610eba61165b565b5b610ec6848285611589565b509392505050565b600081359050610edd81611794565b92915050565b600081519050610ef281611794565b92915050565b600081519050610f07816117ab565b92915050565b600082601f830112610f2257610f21611656565b5b8135610f32848260208601610e8c565b91505092915050565b600081359050610f4a816117c2565b92915050565b600081519050610f5f816117c2565b92915050565b600060208284031215610f7b57610f7a611665565b5b6000610f8984828501610ee3565b91505092915050565b60008060008060808587031215610fac57610fab611665565b5b6000610fba87828801610ece565b9450506020610fcb87828801610ece565b9350506040610fdc87828801610f3b565b925050606085013567ffffffffffffffff811115610ffd57610ffc611660565b5b61100987828801610f0d565b91505092959194509250565b60006020828403121561102b5761102a611665565b5b600061103984828501610ef8565b91505092915050565b60006020828403121561105857611057611665565b5b600061106684828501610f3b565b91505092915050565b60006020828403121561108557611084611665565b5b600061109384828501610f50565b91505092915050565b6110a5816114cd565b82525050565b6110b4816114df565b82525050565b6110c3816114eb565b82525050565b6110d281611541565b82525050565b6110e181611553565b82525050565b60006110f46027836113fd565b91506110ff8261167b565b604082019050919050565b6000611117600b836113fd565b9150611122826116ca565b602082019050919050565b600061113a6024836113fd565b9150611145826116f3565b604082019050919050565b600061115d6018836113fd565b915061116882611742565b602082019050919050565b6000611180601f836113fd565b915061118b8261176b565b602082019050919050565b61119f81611537565b82525050565b60006020820190506111ba600083018461109c565b92915050565b60006060820190506111d5600083018661109c565b6111e2602083018561109c565b6111ef6040830184611196565b949350505050565b600060408201905061120c600083018561109c565b6112196020830184611196565b9392505050565b600060208201905061123560008301846110ab565b92915050565b600060208201905061125060008301846110ba565b92915050565b600060208201905061126b60008301846110c9565b92915050565b600060208201905061128660008301846110d8565b92915050565b600060208201905081810360008301526112a5816110e7565b9050919050565b600060208201905081810360008301526112c58161110a565b9050919050565b600060208201905081810360008301526112e58161112d565b9050919050565b6000602082019050818103600083015261130581611150565b9050919050565b6000602082019050818103600083015261132581611173565b9050919050565b60006020820190506113416000830184611196565b92915050565b600060408201905061135c6000830185611196565b6113696020830184611196565b9392505050565b60006060820190506113856000830186611196565b6113926020830185611196565b61139f604083018461109c565b949350505050565b60006113b16113c2565b90506113bd8282611598565b919050565b6000604051905090565b600067ffffffffffffffff8211156113e7576113e6611627565b5b6113f08261166a565b9050602081019050919050565b600082825260208201905092915050565b600061141982611537565b915061142483611537565b925082611434576114336115f8565b5b828204905092915050565b600061144a82611537565b915061145583611537565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561148e5761148d6115c9565b5b828202905092915050565b60006114a482611537565b91506114af83611537565b9250828210156114c2576114c16115c9565b5b828203905092915050565b60006114d882611517565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061154c82611565565b9050919050565b600061155e82611565565b9050919050565b600061157082611577565b9050919050565b600061158282611517565b9050919050565b82818337600083830152505050565b6115a18261166a565b810181811067ffffffffffffffff821117156115c0576115bf611627565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f5374616b653a204661696c656420746f2074616b6520706f7373657373696f6e60008201527f206f66204e465400000000000000000000000000000000000000000000000000602082015250565b7f7072696365206572726f72000000000000000000000000000000000000000000600082015250565b7f7265636c61696d546f6b656e733a2043616c6c6572206973206e6f742074686560008201527f2044414f00000000000000000000000000000000000000000000000000000000602082015250565b7f4e465420506f6f6c2063616e206e6f7420627579206e6f770000000000000000600082015250565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b61179d816114cd565b81146117a857600080fd5b50565b6117b4816114df565b81146117bf57600080fd5b50565b6117cb81611537565b81146117d657600080fd5b5056fea2646970667358221220d06cde7c429bea0bbd6e4ad33253fa2f4e17ba0dab124713f97ebd77d01567a864736f6c63430008070033