ETH Price: $2,265.26 (+2.56%)

Token

Kiwie1001 (KIWIE1001)
 

Overview

Max Total Supply

47 KIWIE1001

Holders

30

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
keithz.eth
Balance
1 KIWIE1001
0x614c3ce52760343fccb7d908eda39f114620a1e7
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

KIWIE 1001 is a unique concept that brings ownership to Street Art through Blockchain technology. Each of KIWIE 1001 artworks starts with a real-life painting on a wall and then is minted on the blockchain.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Kiwie1001

Compiler Version
v0.5.17+commit.d19bba13

Optimization Enabled:
No with 200 runs

Other Settings:
petersburg EvmVersion
File 1 of 1 : Kiwie1001.sol
pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;

/*
 * @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 GSN 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.
 */
contract Context {
    // Empty internal constructor, to prevent people from mistakenly deploying
    // an instance of this contract, which should be used via inheritance.
    constructor() internal {}

    // solhint-disable-previous-line no-empty-blocks

    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

/**
 * @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.
 *
 * 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.
 */
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() internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(isOwner(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Returns true if the caller is the current owner.
     */
    function isOwner() public view returns (bool) {
        return _msgSender() == _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 onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = 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 onlyOwner {
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     */
    function _transferOwnership(address newOwner) internal {
        require(
            newOwner != address(0),
            "Ownable: new owner is the zero address"
        );
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

/**
 * @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);
}

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
contract IERC721 is IERC165 {
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );
    event Approval(
        address indexed owner,
        address indexed approved,
        uint256 indexed tokenId
    );
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );

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

    /**
     * @dev Returns the owner of the NFT specified by `tokenId`.
     */
    function ownerOf(uint256 tokenId) public view returns (address owner);

    /**
     * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
     * another (`to`).
     *
     *
     *
     * Requirements:
     * - `from`, `to` cannot be zero.
     * - `tokenId` must be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this
     * NFT by either {approve} or {setApprovalForAll}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public;

    /**
     * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
     * another (`to`).
     *
     * Requirements:
     * - If the caller is not `from`, it must be approved to move this NFT by
     * either {approve} or {setApprovalForAll}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public;

    function approve(address to, uint256 tokenId) public;

    function getApproved(uint256 tokenId)
        public
        view
        returns (address operator);

    function setApprovalForAll(address operator, bool _approved) public;

    function isApprovedForAll(address owner, address operator)
        public
        view
        returns (bool);

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public;
}

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
contract IERC721Metadata is IERC721 {
    function name() external view returns (string memory);

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

    function tokenURI(uint256 tokenId) external view returns (string memory);
}

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
contract IERC721Receiver {
    /**
     * @notice Handle the receipt of an NFT
     * @dev The ERC721 smart contract calls this function on the recipient
     * after a {IERC721-safeTransferFrom}. This function MUST return the function selector,
     * otherwise the caller will revert the transaction. The selector to be
     * returned can be obtained as `this.onERC721Received.selector`. This
     * function MAY throw to revert and reject the transfer.
     * Note: the ERC721 contract address is always the message sender.
     * @param operator The address which called `safeTransferFrom` function
     * @param from The address which previously owned the token
     * @param tokenId The NFT identifier which is being transferred
     * @param data Additional data with no specified format
     * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes memory data
    ) public returns (bytes4);
}

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @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) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @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 sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     *
     * _Available since v2.4.0._
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @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) {
        // 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 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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.
     *
     * _Available since v2.4.0._
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts 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 mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message 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.
     *
     * _Available since v2.4.0._
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash =
            0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            codehash := extcodehash(account)
        }
        return (codehash != accountHash && codehash != 0x0);
    }

    /**
     * @dev Converts an `address` into `address payable`. Note that this is
     * simply a type cast: the actual underlying value is not changed.
     *
     * _Available since v2.4.0._
     */
    function toPayable(address account)
        internal
        pure
        returns (address payable)
    {
        return address(uint160(account));
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     *
     * _Available since v2.4.0._
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(
            address(this).balance >= amount,
            "Address: insufficient balance"
        );

        // solhint-disable-next-line avoid-call-value
        (bool success, ) = recipient.call.value(amount)("");
        require(
            success,
            "Address: unable to send value, recipient may have reverted"
        );
    }
}

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}
 * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
 * directly accessed.
 */
library Counters {
    using SafeMath for uint256;

    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        // The {SafeMath} overflow check can be skipped here, see the comment at the top
        counter._value += 1;
    }

    function decrement(Counter storage counter) internal {
        counter._value = counter._value.sub(1);
    }
}

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
contract ERC165 is IERC165 {
    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    constructor() internal {
        // Derived contracts need only register support for their own interfaces,
        // we register support for ERC165 itself here
        _registerInterface(_INTERFACE_ID_ERC165);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     *
     * Time complexity O(1), guaranteed to always use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId)
        external
        view
        returns (bool)
    {
        return _supportedInterfaces[interfaceId];
    }

    /**
     * @dev Registers the contract as an implementer of the interface defined by
     * `interfaceId`. Support of the actual ERC165 interface is automatic and
     * registering its interface id is not required.
     *
     * See {IERC165-supportsInterface}.
     *
     * Requirements:
     *
     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
     */
    function _registerInterface(bytes4 interfaceId) internal {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}

/**
 * @title ERC721 Non-Fungible Token Standard basic implementation
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721 is Context, ERC165, IERC721 {
    using SafeMath for uint256;
    using Address for address;
    using Counters for Counters.Counter;

    // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;

    // Mapping from token ID to owner
    mapping(uint256 => address) private _tokenOwner;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to number of owned token
    mapping(address => Counters.Counter) private _ownedTokensCount;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /*
     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
     *
     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
     *        0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
     */
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;

    constructor() public {
        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721);
    }

    /**
     * @dev Gets the balance of the specified address.
     * @param owner address to query the balance of
     * @return uint256 representing the amount owned by the passed address
     */
    function balanceOf(address owner) public view returns (uint256) {
        require(
            owner != address(0),
            "ERC721: balance query for the zero address"
        );

        return _ownedTokensCount[owner].current();
    }

    /**
     * @dev Gets the owner of the specified token ID.
     * @param tokenId uint256 ID of the token to query the owner of
     * @return address currently marked as the owner of the given token ID
     */
    function ownerOf(uint256 tokenId) public view returns (address) {
        address owner = _tokenOwner[tokenId];
        require(
            owner != address(0),
            "ERC721: owner query for nonexistent token"
        );

        return owner;
    }

    /**
     * @dev Approves another address to transfer the given token ID
     * The zero address indicates there is no approved address.
     * There can only be one approved address per token at a given time.
     * Can only be called by the token owner or an approved operator.
     * @param to address to be approved for the given token ID
     * @param tokenId uint256 ID of the token to be approved
     */
    function approve(address to, uint256 tokenId) public {
        address owner = ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _tokenApprovals[tokenId] = to;
        emit Approval(owner, to, tokenId);
    }

    /**
     * @dev Gets the approved address for a token ID, or zero if no address set
     * Reverts if the token ID does not exist.
     * @param tokenId uint256 ID of the token to query the approval of
     * @return address currently approved for the given token ID
     */
    function getApproved(uint256 tokenId) public view returns (address) {
        require(
            _exists(tokenId),
            "ERC721: approved query for nonexistent token"
        );

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev Sets or unsets the approval of a given operator
     * An operator is allowed to transfer all tokens of the sender on their behalf.
     * @param to operator address to set the approval
     * @param approved representing the status of the approval to be set
     */
    function setApprovalForAll(address to, bool approved) public {
        require(to != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][to] = approved;
        emit ApprovalForAll(_msgSender(), to, approved);
    }

    /**
     * @dev Tells whether an operator is approved by a given owner.
     * @param owner owner address which you want to query the approval of
     * @param operator operator address which you want to query the approval of
     * @return bool whether the given operator is approved by the given owner
     */
    function isApprovedForAll(address owner, address operator)
        public
        view
        returns (bool)
    {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev Transfers the ownership of a given token ID to another address.
     * Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     * Requires the msg.sender to be the owner, approved, or operator.
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public {
        //solhint-disable-next-line max-line-length
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721: transfer caller is not owner nor approved"
        );

        _transferFrom(from, to, tokenId);
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the msg.sender to be the owner, approved, or operator
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the _msgSender() to be the owner, approved, or operator
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes data to send along with a safe transfer check
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public {
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721: transfer caller is not owner nor approved"
        );
        _safeTransferFrom(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the msg.sender to be the owner, approved, or operator
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes data to send along with a safe transfer check
     */
    function _safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal {
        _transferFrom(from, to, tokenId);
        require(
            _checkOnERC721Received(from, to, tokenId, _data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Returns whether the specified token exists.
     * @param tokenId uint256 ID of the token to query the existence of
     * @return bool whether the token exists
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        address owner = _tokenOwner[tokenId];
        return owner != address(0);
    }

    /**
     * @dev Returns whether the given spender can transfer a given token ID.
     * @param spender address of the spender to query
     * @param tokenId uint256 ID of the token to be transferred
     * @return bool whether the msg.sender is approved for the given token ID,
     * is an operator of the owner, or is the owner of the token
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId)
        internal
        view
        returns (bool)
    {
        require(
            _exists(tokenId),
            "ERC721: operator query for nonexistent token"
        );
        address owner = ownerOf(tokenId);
        return (spender == owner ||
            getApproved(tokenId) == spender ||
            isApprovedForAll(owner, spender));
    }

    /**
     * @dev Internal function to safely mint a new token.
     * Reverts if the given token ID already exists.
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * @param to The address that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     */
    function _safeMint(address to, uint256 tokenId) internal {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Internal function to safely mint a new token.
     * Reverts if the given token ID already exists.
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * @param to The address that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     * @param _data bytes data to send along with a safe transfer check
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, _data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Internal function to mint a new token.
     * Reverts if the given token ID already exists.
     * @param to The address that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     */
    function _mint(address to, uint256 tokenId) internal {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _tokenOwner[tokenId] = to;
        _ownedTokensCount[to].increment();

        emit Transfer(address(0), to, tokenId);
    }

    /**
     * @dev Internal function to burn a specific token.
     * Reverts if the token does not exist.
     * Deprecated, use {_burn} instead.
     * @param owner owner of the token to burn
     * @param tokenId uint256 ID of the token being burned
     */
    function _burn(address owner, uint256 tokenId) internal {
        require(
            ownerOf(tokenId) == owner,
            "ERC721: burn of token that is not own"
        );

        _clearApproval(tokenId);

        _ownedTokensCount[owner].decrement();
        _tokenOwner[tokenId] = address(0);

        emit Transfer(owner, address(0), tokenId);
    }

    /**
     * @dev Internal function to burn a specific token.
     * Reverts if the token does not exist.
     * @param tokenId uint256 ID of the token being burned
     */
    function _burn(uint256 tokenId) internal {
        _burn(ownerOf(tokenId), tokenId);
    }

    /**
     * @dev Internal function to transfer ownership of a given token ID to another address.
     * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function _transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) internal {
        require(
            ownerOf(tokenId) == from,
            "ERC721: transfer of token that is not own"
        );
        require(to != address(0), "ERC721: transfer to the zero address");

        _clearApproval(tokenId);

        _ownedTokensCount[from].decrement();
        _ownedTokensCount[to].increment();

        _tokenOwner[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * This is an internal detail of the `ERC721` contract and its use is deprecated.
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal returns (bool) {
        if (!to.isContract()) {
            return true;
        }
        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) =
            to.call(
                abi.encodeWithSelector(
                    IERC721Receiver(to).onERC721Received.selector,
                    _msgSender(),
                    from,
                    tokenId,
                    _data
                )
            );
        if (!success) {
            if (returndata.length > 0) {
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert("ERC721: transfer to non ERC721Receiver implementer");
            }
        } else {
            bytes4 retval = abi.decode(returndata, (bytes4));
            return (retval == _ERC721_RECEIVED);
        }
    }

    /**
     * @dev Private function to clear current approval of a given token ID.
     * @param tokenId uint256 ID of the token to be transferred
     */
    function _clearApproval(uint256 tokenId) private {
        if (_tokenApprovals[tokenId] != address(0)) {
            _tokenApprovals[tokenId] = address(0);
        }
    }
}

/**
 * @title ERC721 Burnable Token
 * @dev ERC721 Token that can be irreversibly burned (destroyed).
 */
contract ERC721Burnable is Context, ERC721 {
    /**
     * @dev Burns a specific ERC721 token.
     * @param tokenId uint256 id of the ERC721 token to be burned.
     */
    function burn(uint256 tokenId) public {
        //solhint-disable-next-line max-line-length
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721Burnable: caller is not owner nor approved"
        );
        _burn(tokenId);
    }
}

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
contract IERC721Enumerable is IERC721 {
    function totalSupply() public view returns (uint256);

    function tokenOfOwnerByIndex(address owner, uint256 index)
        public
        view
        returns (uint256 tokenId);

    function tokenByIndex(uint256 index) public view returns (uint256);
}

/**
 * @title ERC-721 Non-Fungible Token with optional enumeration extension logic
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721Enumerable is Context, ERC165, ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => uint256[]) private _ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) private _ownedTokensIndex;

    // Array with all token ids, used for enumeration
    uint256[] private _allTokens;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) private _allTokensIndex;

    /*
     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd
     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
     *
     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
     */
    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;

    /**
     * @dev Constructor function.
     */
    constructor() public {
        // register the supported interface to conform to ERC721Enumerable via ERC165
        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
    }

    /**
     * @dev Gets the token ID at a given index of the tokens list of the requested owner.
     * @param owner address owning the tokens list to be accessed
     * @param index uint256 representing the index to be accessed of the requested tokens list
     * @return uint256 token ID at the given index of the tokens list owned by the requested address
     */
    function tokenOfOwnerByIndex(address owner, uint256 index)
        public
        view
        returns (uint256)
    {
        require(
            index < balanceOf(owner),
            "ERC721Enumerable: owner index out of bounds"
        );
        return _ownedTokens[owner][index];
    }

    /**
     * @dev Gets the total amount of tokens stored by the contract.
     * @return uint256 representing the total amount of tokens
     */
    function totalSupply() public view returns (uint256) {
        return _allTokens.length;
    }

    /**
     * @dev Gets the token ID at a given index of all the tokens in this contract
     * Reverts if the index is greater or equal to the total number of tokens.
     * @param index uint256 representing the index to be accessed of the tokens list
     * @return uint256 token ID at the given index of the tokens list
     */
    function tokenByIndex(uint256 index) public view returns (uint256) {
        require(
            index < totalSupply(),
            "ERC721Enumerable: global index out of bounds"
        );
        return _allTokens[index];
    }

    /**
     * @dev Internal function to transfer ownership of a given token ID to another address.
     * As opposed to transferFrom, this imposes no restrictions on msg.sender.
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function _transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) internal {
        super._transferFrom(from, to, tokenId);

        _removeTokenFromOwnerEnumeration(from, tokenId);

        _addTokenToOwnerEnumeration(to, tokenId);
    }

    /**
     * @dev Internal function to mint a new token.
     * Reverts if the given token ID already exists.
     * @param to address the beneficiary that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     */
    function _mint(address to, uint256 tokenId) internal {
        super._mint(to, tokenId);

        _addTokenToOwnerEnumeration(to, tokenId);

        _addTokenToAllTokensEnumeration(tokenId);
    }

    /**
     * @dev Internal function to burn a specific token.
     * Reverts if the token does not exist.
     * Deprecated, use {ERC721-_burn} instead.
     * @param owner owner of the token to burn
     * @param tokenId uint256 ID of the token being burned
     */
    function _burn(address owner, uint256 tokenId) internal {
        super._burn(owner, tokenId);

        _removeTokenFromOwnerEnumeration(owner, tokenId);
        // Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund
        _ownedTokensIndex[tokenId] = 0;

        _removeTokenFromAllTokensEnumeration(tokenId);
    }

    /**
     * @dev Gets the list of token IDs of the requested owner.
     * @param owner address owning the tokens
     * @return uint256[] List of token IDs owned by the requested address
     */
    function _tokensOfOwner(address owner)
        internal
        view
        returns (uint256[] storage)
    {
        return _ownedTokens[owner];
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        _ownedTokensIndex[tokenId] = _ownedTokens[to].length;
        _ownedTokens[to].push(tokenId);
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId)
        private
    {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _ownedTokens[from].length.sub(1);
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        _ownedTokens[from].length--;

        // Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occupied by
        // lastTokenId, or just over the end of the array if the token was the last one).
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length.sub(1);
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        _allTokens.length--;
        _allTokensIndex[tokenId] = 0;
    }
}

library UintLibrary {
    function toString(uint256 _i) internal pure returns (string memory) {
        if (_i == 0) {
            return "0";
        }
        uint256 j = _i;
        uint256 len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint256 k = len - 1;
        while (_i != 0) {
            bstr[k--] = bytes1(uint8(48 + (_i % 10)));
            _i /= 10;
        }
        return string(bstr);
    }
}

library StringLibrary {
    using UintLibrary for uint256;

    function append(string memory _a, string memory _b)
        internal
        pure
        returns (string memory)
    {
        bytes memory _ba = bytes(_a);
        bytes memory _bb = bytes(_b);
        bytes memory bab = new bytes(_ba.length + _bb.length);
        uint256 k = 0;
        for (uint256 i = 0; i < _ba.length; i++) bab[k++] = _ba[i];
        for (uint256 i = 0; i < _bb.length; i++) bab[k++] = _bb[i];
        return string(bab);
    }

    function append(
        string memory _a,
        string memory _b,
        string memory _c
    ) internal pure returns (string memory) {
        bytes memory _ba = bytes(_a);
        bytes memory _bb = bytes(_b);
        bytes memory _bc = bytes(_c);
        bytes memory bbb = new bytes(_ba.length + _bb.length + _bc.length);
        uint256 k = 0;
        for (uint256 i = 0; i < _ba.length; i++) bbb[k++] = _ba[i];
        for (uint256 i = 0; i < _bb.length; i++) bbb[k++] = _bb[i];
        for (uint256 i = 0; i < _bc.length; i++) bbb[k++] = _bc[i];
        return string(bbb);
    }

    function recover(
        string memory message,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        bytes memory msgBytes = bytes(message);
        bytes memory fullMessage =
            concat(
                bytes("\x19Ethereum Signed Message:\n"),
                bytes(msgBytes.length.toString()),
                msgBytes,
                new bytes(0),
                new bytes(0),
                new bytes(0),
                new bytes(0)
            );
        return ecrecover(keccak256(fullMessage), v, r, s);
    }

    function concat(
        bytes memory _ba,
        bytes memory _bb,
        bytes memory _bc,
        bytes memory _bd,
        bytes memory _be,
        bytes memory _bf,
        bytes memory _bg
    ) internal pure returns (bytes memory) {
        bytes memory resultBytes =
            new bytes(
                _ba.length +
                    _bb.length +
                    _bc.length +
                    _bd.length +
                    _be.length +
                    _bf.length +
                    _bg.length
            );
        uint256 k = 0;
        for (uint256 i = 0; i < _ba.length; i++) resultBytes[k++] = _ba[i];
        for (uint256 i = 0; i < _bb.length; i++) resultBytes[k++] = _bb[i];
        for (uint256 i = 0; i < _bc.length; i++) resultBytes[k++] = _bc[i];
        for (uint256 i = 0; i < _bd.length; i++) resultBytes[k++] = _bd[i];
        for (uint256 i = 0; i < _be.length; i++) resultBytes[k++] = _be[i];
        for (uint256 i = 0; i < _bf.length; i++) resultBytes[k++] = _bf[i];
        for (uint256 i = 0; i < _bg.length; i++) resultBytes[k++] = _bg[i];
        return resultBytes;
    }
}

contract HasContractURI is ERC165 {
    string public contractURI;

    /*
     * bytes4(keccak256('contractURI()')) == 0xe8a3d485
     */
    bytes4 private constant _INTERFACE_ID_CONTRACT_URI = 0xe8a3d485;

    constructor(string memory _contractURI) public {
        contractURI = _contractURI;
        _registerInterface(_INTERFACE_ID_CONTRACT_URI);
    }

    /**
     * @dev Internal function to set the contract URI
     * @param _contractURI string URI prefix to assign
     */
    function _setContractURI(string memory _contractURI) internal {
        contractURI = _contractURI;
    }
}

contract HasTokenURI {
    using StringLibrary for string;

    //Token URI prefix
    string public tokenURIPrefix;

    // Optional mapping for token URIs
    mapping(uint256 => string) private _tokenURIs;

    constructor(string memory _tokenURIPrefix) public {
        tokenURIPrefix = _tokenURIPrefix;
    }

    /**
     * @dev Returns an URI for a given token ID.
     * Throws if the token ID does not exist. May return an empty string.
     * @param tokenId uint256 ID of the token to query
     */
    function _tokenURI(uint256 tokenId) internal view returns (string memory) {
        return tokenURIPrefix.append(_tokenURIs[tokenId]);
    }

    /**
     * @dev Internal function to set the token URI for a given token.
     * Reverts if the token ID does not exist.
     * @param tokenId uint256 ID of the token to set its URI
     * @param uri string URI to assign
     */
    function _setTokenURI(uint256 tokenId, string memory uri) internal {
        _tokenURIs[tokenId] = uri;
    }

    /**
     * @dev Internal function to set the token URI prefix.
     * @param _tokenURIPrefix string URI prefix to assign
     */
    function _setTokenURIPrefix(string memory _tokenURIPrefix) internal {
        tokenURIPrefix = _tokenURIPrefix;
    }

    function _clearTokenURI(uint256 tokenId) internal {
        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }
    }
}

contract HasSecondarySaleFees is ERC165 {
    event SecondarySaleFees(
        uint256 tokenId,
        address[] recipients,
        uint256[] bps
    );

    /*
     * bytes4(keccak256('getFeeBps(uint256)')) == 0x0ebd4c7f
     * bytes4(keccak256('getFeeRecipients(uint256)')) == 0xb9c4d9fb
     *
     * => 0x0ebd4c7f ^ 0xb9c4d9fb == 0xb7799584
     */
    bytes4 private constant _INTERFACE_ID_FEES = 0xb7799584;

    constructor() public {
        _registerInterface(_INTERFACE_ID_FEES);
    }

    function getFeeRecipients(uint256 id)
        public
        view
        returns (address payable[] memory);

    function getFeeBps(uint256 id) public view returns (uint256[] memory);
}

/**
 * @title Full ERC721 Token with support for tokenURIPrefix
 * This implementation includes all the required and some optional functionality of the ERC721 standard
 * Moreover, it includes approve all functionality using operator terminology
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721Base is
    HasSecondarySaleFees,
    ERC721,
    HasContractURI,
    HasTokenURI,
    ERC721Enumerable
{
    // Token name
    string public name;

    // Token symbol
    string public symbol;

    struct Fee {
        address payable recipient;
        uint256 value;
    }

    // id => fees
    mapping(uint256 => Fee[]) public fees;

    /*
     *     bytes4(keccak256('name()')) == 0x06fdde03
     *     bytes4(keccak256('symbol()')) == 0x95d89b41
     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
     *
     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
     */
    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;

    /**
     * @dev Constructor function
     */
    constructor(
        string memory _name,
        string memory _symbol,
        string memory contractURI,
        string memory _tokenURIPrefix
    ) public HasContractURI(contractURI) HasTokenURI(_tokenURIPrefix) {
        name = _name;
        symbol = _symbol;

        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721_METADATA);
    }

    function getFeeRecipients(uint256 id)
        public
        view
        returns (address payable[] memory)
    {
        Fee[] memory _fees = fees[id];
        address payable[] memory result = new address payable[](_fees.length);
        for (uint256 i = 0; i < _fees.length; i++) {
            result[i] = _fees[i].recipient;
        }
        return result;
    }

    function getFeeBps(uint256 id) public view returns (uint256[] memory) {
        Fee[] memory _fees = fees[id];
        uint256[] memory result = new uint256[](_fees.length);
        for (uint256 i = 0; i < _fees.length; i++) {
            result[i] = _fees[i].value;
        }
        return result;
    }

    function _mint(
        address to,
        uint256 tokenId,
        Fee[] memory _fees
    ) internal {
        _mint(to, tokenId);
        address[] memory recipients = new address[](_fees.length);
        uint256[] memory bps = new uint256[](_fees.length);
        for (uint256 i = 0; i < _fees.length; i++) {
            require(
                _fees[i].recipient != address(0x0),
                "Recipient should be present"
            );
            require(_fees[i].value != 0, "Fee value should be positive");
            fees[tokenId].push(_fees[i]);
            recipients[i] = _fees[i].recipient;
            bps[i] = _fees[i].value;
        }
        if (_fees.length > 0) {
            emit SecondarySaleFees(tokenId, recipients, bps);
        }
    }

    /**
     * @dev Returns an URI for a given token ID.
     * Throws if the token ID does not exist. May return an empty string.
     * @param tokenId uint256 ID of the token to query
     */
    function tokenURI(uint256 tokenId) external view returns (string memory) {
        require(
            _exists(tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );
        return super._tokenURI(tokenId);
    }

    /**
     * @dev Internal function to set the token URI for a given token.
     * Reverts if the token ID does not exist.
     * @param tokenId uint256 ID of the token to set its URI
     * @param uri string URI to assign
     */
    function _setTokenURI(uint256 tokenId, string memory uri) internal {
        require(
            _exists(tokenId),
            "ERC721Metadata: URI set of nonexistent token"
        );
        super._setTokenURI(tokenId, uri);
    }

    /**
     * @dev Internal function to burn a specific token.
     * Reverts if the token does not exist.
     * Deprecated, use _burn(uint256) instead.
     * @param owner owner of the token to burn
     * @param tokenId uint256 ID of the token being burned by the msg.sender
     */
    function _burn(address owner, uint256 tokenId) internal {
        super._burn(owner, tokenId);
        _clearTokenURI(tokenId);
    }
}

/**
 * @title Kiwie1001Toekn
 */
contract Kiwie1001 is
    Ownable,
    IERC721,
    IERC721Metadata,
    ERC721Burnable,
    ERC721Base
{
    uint public _currentIdx;
    //mapping(uint256 => bool) public isAlive;
    //mapping(uint256 => string) public aliveIPFSHash;
    //mapping(uint256 => string) public ghostIPFSHash;


    constructor() 
        public ERC721Base("Kiwie1001", "KIWIE1001", "https://api-mainnet.rarible.com/contractMetadata/{address}", "https://gateway.pinata.cloud/ipfs/") 
    {
        transferOwnership(msg.sender);
        _currentIdx = 0;
    }

    //Fees = % * 100. So 5% = 500
    function mint(string memory tokenURI, Fee[] memory _fees) onlyOwner public 
    {
        _currentIdx = _currentIdx + 1;
        uint256 tokenId = _currentIdx;

        _mint(msg.sender, tokenId, _fees);
        _setTokenURI(tokenId, tokenURI);
    }

    function setTokenURI(uint256 tokenId, string memory tokenURI) public onlyOwner 
    {
       _setTokenURI(tokenId, tokenURI);
    }

    function setTokenURIPrefix(string memory tokenURIPrefix) public onlyOwner 
    {
        _setTokenURIPrefix(tokenURIPrefix);
    }

    function setContractURI(string memory contractURI) public onlyOwner 
    {
        _setContractURI(contractURI);
    }
}

Settings
{
  "remappings": [],
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "evmVersion": "petersburg",
  "libraries": {},
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","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":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"recipients","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"bps","type":"uint256[]"}],"name":"SecondarySaleFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"_currentIdx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"fees","outputs":[{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getFeeBps","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getFeeRecipients","outputs":[{"internalType":"address payable[]","name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"tokenURI","type":"string"},{"components":[{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct ERC721Base.Fee[]","name":"_fees","type":"tuple[]"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"contractURI","type":"string"}],"name":"setContractURI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"tokenURI","type":"string"}],"name":"setTokenURI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"tokenURIPrefix","type":"string"}],"name":"setTokenURIPrefix","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenURIPrefix","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b506040518060400160405280600981526020017f4b697769653130303100000000000000000000000000000000000000000000008152506040518060400160405280600981526020017f4b495749453130303100000000000000000000000000000000000000000000008152506040518060600160405280603a815260200162004f92603a913960405180606001604052806022815260200162004fcc6022913980826000620000c66200027d60201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3506200017c6301ffc9a760e01b6200028560201b60201c565b6200019463b779958460e01b6200028560201b60201c565b620001ac6380ac58cd60e01b6200028560201b60201c565b8060069080519060200190620001c49291906200055a565b50620001dd63e8a3d48560e01b6200028560201b60201c565b508060079080519060200190620001f69291906200055a565b50506200021063780e9d6360e01b6200028560201b60201c565b83600d9080519060200190620002289291906200055a565b5082600e9080519060200190620002419291906200055a565b506200025a635b5e139f60e01b6200028560201b60201c565b505050506200026f336200035d60201b60201c565b60006010819055506200076c565b600033905090565b63ffffffff60e01b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415620002f1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002e89062000717565b60405180910390fd5b6001806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b6200036d620003c360201b60201c565b620003af576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003a69062000739565b60405180910390fd5b620003c0816200042960201b60201c565b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166200040d6200027d60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156200049c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200049390620006f5565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200059d57805160ff1916838001178555620005ce565b82800160010185558215620005ce579182015b82811115620005cd578251825591602001919060010190620005b0565b5b509050620005dd9190620005e1565b5090565b6200060691905b8082111562000602576000816000905550600101620005e8565b5090565b90565b6000620006186026836200075b565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600062000680601c836200075b565b91507f4552433136353a20696e76616c696420696e74657266616365206964000000006000830152602082019050919050565b6000620006c26020836200075b565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006020820190508181036000830152620007108162000609565b9050919050565b60006020820190508181036000830152620007328162000671565b9050919050565b600060208201905081810360008301526200075481620006b3565b9050919050565b600082825260208201905092915050565b614816806200077c6000396000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c8063715018a61161010f578063b88d4fde116100a2578063e8a3d48511610071578063e8a3d485146105a3578063e985e9c5146105c1578063f2fde38b146105f1578063f88190b11461060d576101e5565b8063b88d4fde14610509578063b9c4d9fb14610525578063c0ac998314610555578063c87b56dd14610573576101e5565b8063938e3d7b116100de578063938e3d7b1461049757806395d89b41146104b357806399e0dd7c146104d1578063a22cb465146104ed576101e5565b8063715018a6146104335780637ba3c4581461043d5780638da5cb5b1461045b5780638f32d59b14610479576101e5565b806323b872dd116101875780634f6ccce7116101565780634f6ccce7146103725780636308f1cd146103a25780636352211e146103d357806370a0823114610403576101e5565b806323b872dd146102ee5780632f745c591461030a57806342842e0e1461033a57806342966c6814610356576101e5565b8063095ea7b3116101c3578063095ea7b3146102685780630ebd4c7f14610284578063162094c4146102b457806318160ddd146102d0576101e5565b806301ffc9a7146101ea57806306fdde031461021a578063081812fc14610238575b600080fd5b61020460048036036101ff91908101906133b2565b610629565b6040516102119190614142565b60405180910390f35b610222610691565b60405161022f919061415d565b60405180910390f35b610252600480360361024d91908101906134b1565b61072f565b60405161025f919061406e565b60405180910390f35b610282600480360361027d9190810190613376565b6107b4565b005b61029e600480360361029991908101906134b1565b61096f565b6040516102ab9190614120565b60405180910390f35b6102ce60048036036102c991908101906134da565b610ac9565b005b6102d8610b1e565b6040516102e59190614481565b60405180910390f35b61030860048036036103039190810190613270565b610b2b565b005b610324600480360361031f9190810190613376565b610b8b565b6040516103319190614481565b60405180910390f35b610354600480360361034f9190810190613270565b610c34565b005b610370600480360361036b91908101906134b1565b610c54565b005b61038c600480360361038791908101906134b1565b610cb0565b6040516103999190614481565b60405180910390f35b6103bc60048036036103b7919081019061352e565b610d1a565b6040516103ca9291906140d5565b60405180910390f35b6103ed60048036036103e891908101906134b1565b610d78565b6040516103fa919061406e565b60405180910390f35b61041d6004803603610418919081019061320b565b610e2a565b60405161042a9190614481565b60405180910390f35b61043b610ee9565b005b610445610fef565b6040516104529190614481565b60405180910390f35b610463610ff5565b604051610470919061406e565b60405180910390f35b61048161101e565b60405161048e9190614142565b60405180910390f35b6104b160048036036104ac9190810190613404565b61107c565b005b6104bb6110cf565b6040516104c8919061415d565b60405180910390f35b6104eb60048036036104e69190810190613404565b61116d565b005b6105076004803603610502919081019061333a565b6111c0565b005b610523600480360361051e91908101906132bf565b611341565b005b61053f600480360361053a91908101906134b1565b6113a3565b60405161054c91906140fe565b60405180910390f35b61055d61152b565b60405161056a919061415d565b60405180910390f35b61058d600480360361058891908101906134b1565b6115c9565b60405161059a919061417f565b60405180910390f35b6105ab611623565b6040516105b8919061415d565b60405180910390f35b6105db60048036036105d69190810190613234565b6116c1565b6040516105e89190614142565b60405180910390f35b61060b6004803603610606919081019061320b565b611755565b005b61062760048036036106229190810190613445565b6117a8565b005b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b600d8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107275780601f106106fc57610100808354040283529160200191610727565b820191906000526020600020905b81548152906001019060200180831161070a57829003601f168201915b505050505081565b600061073a8261181c565b610779576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090614321565b60405180910390fd5b6003600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006107bf82610d78565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610830576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610827906143c1565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1661084f61188e565b73ffffffffffffffffffffffffffffffffffffffff16148061087e575061087d8161087861188e565b6116c1565b5b6108bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b4906142a1565b60405180910390fd5b826003600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b606080600f6000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610a3757838290600052602060002090600202016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481525050815260200190600101906109a5565b50505050905060608151604051908082528060200260200182016040528015610a6f5781602001602082028038833980820191505090505b50905060008090505b8251811015610abe57828181518110610a8d57fe5b602002602001015160200151828281518110610aa557fe5b6020026020010181815250508080600101915050610a78565b508092505050919050565b610ad161101e565b610b10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0790614361565b60405180910390fd5b610b1a8282611896565b5050565b6000600b80549050905090565b610b3c610b3661188e565b826118ec565b610b7b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b72906143e1565b60405180910390fd5b610b868383836119ca565b505050565b6000610b9683610e2a565b8210610bd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bce906141c1565b60405180910390fd5b600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110610c2157fe5b9060005260206000200154905092915050565b610c4f83838360405180602001604052806000815250611341565b505050565b610c65610c5f61188e565b826118ec565b610ca4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c9b90614461565b60405180910390fd5b610cad816119ee565b50565b6000610cba610b1e565b8210610cfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cf290614401565b60405180910390fd5b600b8281548110610d0857fe5b90600052602060002001549050919050565b600f6020528160005260406000208181548110610d3357fe5b9060005260206000209060020201600091509150508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154905082565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610e21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e18906142e1565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610e9b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e92906142c1565b60405180910390fd5b610ee2600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611a03565b9050919050565b610ef161101e565b610f30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2790614361565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60105481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661106061188e565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b61108461101e565b6110c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ba90614361565b60405180910390fd5b6110cc81611a11565b50565b600e8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156111655780601f1061113a57610100808354040283529160200191611165565b820191906000526020600020905b81548152906001019060200180831161114857829003601f168201915b505050505081565b61117561101e565b6111b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ab90614361565b60405180910390fd5b6111bd81611a2b565b50565b6111c861188e565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611236576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122d90614261565b60405180910390fd5b806005600061124361188e565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff166112f061188e565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516113359190614142565b60405180910390a35050565b61135261134c61188e565b836118ec565b611391576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611388906143e1565b60405180910390fd5b61139d84848484611a45565b50505050565b606080600f6000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561146b57838290600052602060002090600202016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481525050815260200190600101906113d9565b505050509050606081516040519080825280602002602001820160405280156114a35781602001602082028038833980820191505090505b50905060008090505b8251811015611520578281815181106114c157fe5b6020026020010151600001518282815181106114d957fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080806001019150506114ac565b508092505050919050565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156115c15780601f10611596576101008083540402835291602001916115c1565b820191906000526020600020905b8154815290600101906020018083116115a457829003601f168201915b505050505081565b60606115d48261181c565b611613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161160a906143a1565b60405180910390fd5b61161c82611aa1565b9050919050565b60068054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156116b95780601f1061168e576101008083540402835291602001916116b9565b820191906000526020600020905b81548152906001019060200180831161169c57829003601f168201915b505050505081565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b61175d61101e565b61179c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161179390614361565b60405180910390fd5b6117a581611c02565b50565b6117b061101e565b6117ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e690614361565b60405180910390fd5b6001601054016010819055506000601054905061180d338284611d30565b6118178184611896565b505050565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415915050919050565b600033905090565b61189f8261181c565b6118de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118d590614341565b60405180910390fd5b6118e88282612024565b5050565b60006118f78261181c565b611936576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192d90614281565b60405180910390fd5b600061194183610d78565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806119b057508373ffffffffffffffffffffffffffffffffffffffff166119988461072f565b73ffffffffffffffffffffffffffffffffffffffff16145b806119c157506119c081856116c1565b5b91505092915050565b6119d5838383612050565b6119df838261227f565b6119e9828261241d565b505050565b611a006119fa82610d78565b826124e4565b50565b600081600001549050919050565b8060069080519060200190611a27929190612efd565b5050565b8060079080519060200190611a41929190612efd565b5050565b611a508484846119ca565b611a5c848484846124fb565b611a9b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a92906141e1565b60405180910390fd5b50505050565b6060611bfb600860008481526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611b4d5780601f10611b2257610100808354040283529160200191611b4d565b820191906000526020600020905b815481529060010190602001808311611b3057829003601f168201915b505050505060078054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611be85780601f10611bbd57610100808354040283529160200191611be8565b820191906000526020600020905b815481529060010190602001808311611bcb57829003601f168201915b50505050506126f590919063ffffffff16565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6990614201565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b611d3a8383612838565b60608151604051908082528060200260200182016040528015611d6c5781602001602082028038833980820191505090505b50905060608251604051908082528060200260200182016040528015611da15781602001602082028038833980820191505090505b50905060008090505b8351811015611fd657600073ffffffffffffffffffffffffffffffffffffffff16848281518110611dd757fe5b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff161415611e3a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e3190614441565b60405180910390fd5b6000848281518110611e4857fe5b6020026020010151602001511415611e95576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8c906141a1565b60405180910390fd5b600f6000868152602001908152602001600020848281518110611eb457fe5b60200260200101519080600181540180825580915050906001820390600052602060002090600202016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155505050838181518110611f4757fe5b602002602001015160000151838281518110611f5f57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050838181518110611fa557fe5b602002602001015160200151828281518110611fbd57fe5b6020026020010181815250508080600101915050611daa565b5060008351111561201d577f99aba1d63749cfd5ad1afda7c4663840924d54eb5f005bbbeadedc6ec13674b28483836040516120149392919061449c565b60405180910390a15b5050505050565b8060086000848152602001908152602001600020908051906020019061204b929190612efd565b505050565b8273ffffffffffffffffffffffffffffffffffffffff1661207082610d78565b73ffffffffffffffffffffffffffffffffffffffff16146120c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120bd90614381565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612136576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161212d90614241565b60405180910390fd5b61213f81612859565b612186600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612917565b6121cd600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061293a565b816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60006122d76001600960008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905061295090919063ffffffff16565b90506000600a60008481526020019081526020016000205490508181146123c4576000600960008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838154811061234457fe5b9060005260206000200154905080600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838154811061239c57fe5b906000526020600020018190555081600a600083815260200190815260200160002081905550505b600960008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054809190600190036124169190612f7d565b5050505050565b600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050600a600083815260200190815260200160002081905550600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190806001815401808255809150509060018203906000526020600020016000909192909190915055505050565b6124ee828261299a565b6124f7816129d4565b5050565b600061251c8473ffffffffffffffffffffffffffffffffffffffff16612a26565b61252957600190506126ed565b600060608573ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1663150b7a02905060e01b61256d61188e565b8988886040516024016125839493929190614089565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516125ed9190614057565b6000604051808303816000865af19150503d806000811461262a576040519150601f19603f3d011682016040523d82523d6000602084013e61262f565b606091505b5091509150816126875760008151111561264c5780518082602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161267e906141e1565b60405180910390fd5b60008180602001905161269d91908101906133db565b905063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161493505050505b949350505050565b6060808390506060839050606081518351016040519080825280601f01601f1916602001820160405280156127395781602001600182028038833980820191505090505b509050600080905060008090505b84518110156127b55784818151811061275c57fe5b602001015160f81c60f81b83838060010194508151811061277957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050612747565b5060008090505b835181101561282a578381815181106127d157fe5b602001015160f81c60f81b8383806001019450815181106127ee57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506127bc565b508194505050505092915050565b6128428282612a71565b61284c828261241d565b61285581612c23565b5050565b600073ffffffffffffffffffffffffffffffffffffffff166003600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146129145760006003600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b61292f6001826000015461295090919063ffffffff16565b816000018190555050565b6001816000016000828254019250508190555050565b600061299283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612c6f565b905092915050565b6129a48282612cca565b6129ae828261227f565b6000600a6000838152602001908152602001600020819055506129d081612e43565b5050565b60006008600083815260200190815260200160002080546001816001161561010002031660029004905014612a2357600860008281526020019081526020016000206000612a229190612fa9565b5b50565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f9150808214158015612a6857506000801b8214155b92505050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ad890614301565b60405180910390fd5b612aea8161181c565b15612b2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b2190614221565b60405180910390fd5b816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612bc3600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061293a565b808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600b80549050600c600083815260200190815260200160002081905550600b81908060018154018082558091505090600182039060005260206000200160009091929091909150555050565b6000838311158290612cb7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cae919061417f565b60405180910390fd5b5060008385039050809150509392505050565b8173ffffffffffffffffffffffffffffffffffffffff16612cea82610d78565b73ffffffffffffffffffffffffffffffffffffffff1614612d40576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d3790614421565b60405180910390fd5b612d4981612859565b612d90600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612917565b60006002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b6000612e5e6001600b8054905061295090919063ffffffff16565b90506000600c60008481526020019081526020016000205490506000600b8381548110612e8757fe5b9060005260206000200154905080600b8381548110612ea257fe5b906000526020600020018190555081600c600083815260200190815260200160002081905550600b805480919060019003612edd9190612f7d565b506000600c60008681526020019081526020016000208190555050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612f3e57805160ff1916838001178555612f6c565b82800160010185558215612f6c579182015b82811115612f6b578251825591602001919060010190612f50565b5b509050612f799190612ff1565b5090565b815481835581811115612fa457818360005260206000209182019101612fa39190612ff1565b5b505050565b50805460018160011615610100020316600290046000825580601f10612fcf5750612fee565b601f016020900490600052602060002090810190612fed9190612ff1565b5b50565b61301391905b8082111561300f576000816000905550600101612ff7565b5090565b90565b60008135905061302581614760565b92915050565b60008135905061303a81614777565b92915050565b600082601f83011261305157600080fd5b813561306461305f8261450e565b6144e1565b9150818183526020840193506020810190508385604084028201111561308957600080fd5b60005b838110156130b9578161309f88826131aa565b84526020840193506040830192505060018101905061308c565b5050505092915050565b6000813590506130d28161478e565b92915050565b6000813590506130e7816147a5565b92915050565b6000815190506130fc816147a5565b92915050565b600082601f83011261311357600080fd5b813561312661312182614536565b6144e1565b9150808252602083016020830185838301111561314257600080fd5b61314d83828461470d565b50505092915050565b600082601f83011261316757600080fd5b813561317a61317582614562565b6144e1565b9150808252602083016020830185838301111561319657600080fd5b6131a183828461470d565b50505092915050565b6000604082840312156131bc57600080fd5b6131c660406144e1565b905060006131d68482850161302b565b60008301525060206131ea848285016131f6565b60208301525092915050565b600081359050613205816147bc565b92915050565b60006020828403121561321d57600080fd5b600061322b84828501613016565b91505092915050565b6000806040838503121561324757600080fd5b600061325585828601613016565b925050602061326685828601613016565b9150509250929050565b60008060006060848603121561328557600080fd5b600061329386828701613016565b93505060206132a486828701613016565b92505060406132b5868287016131f6565b9150509250925092565b600080600080608085870312156132d557600080fd5b60006132e387828801613016565b94505060206132f487828801613016565b9350506040613305878288016131f6565b925050606085013567ffffffffffffffff81111561332257600080fd5b61332e87828801613102565b91505092959194509250565b6000806040838503121561334d57600080fd5b600061335b85828601613016565b925050602061336c858286016130c3565b9150509250929050565b6000806040838503121561338957600080fd5b600061339785828601613016565b92505060206133a8858286016131f6565b9150509250929050565b6000602082840312156133c457600080fd5b60006133d2848285016130d8565b91505092915050565b6000602082840312156133ed57600080fd5b60006133fb848285016130ed565b91505092915050565b60006020828403121561341657600080fd5b600082013567ffffffffffffffff81111561343057600080fd5b61343c84828501613156565b91505092915050565b6000806040838503121561345857600080fd5b600083013567ffffffffffffffff81111561347257600080fd5b61347e85828601613156565b925050602083013567ffffffffffffffff81111561349b57600080fd5b6134a785828601613040565b9150509250929050565b6000602082840312156134c357600080fd5b60006134d1848285016131f6565b91505092915050565b600080604083850312156134ed57600080fd5b60006134fb858286016131f6565b925050602083013567ffffffffffffffff81111561351857600080fd5b61352485828601613156565b9150509250929050565b6000806040838503121561354157600080fd5b600061354f858286016131f6565b9250506020613560858286016131f6565b9150509250929050565b600061357683836135b2565b60208301905092915050565b600061358e83836135d0565b60208301905092915050565b60006135a68383614039565b60208301905092915050565b6135bb81614699565b82525050565b6135ca81614699565b82525050565b6135d981614687565b82525050565b6135e881614687565b82525050565b60006135f9826145be565b6136038185614627565b935061360e8361458e565b8060005b8381101561363f5781516136268882613582565b975061363183614600565b925050600181019050613612565b5085935050505092915050565b6000613657826145c9565b6136618185614638565b935061366c8361459e565b8060005b8381101561369d578151613684888261356a565b975061368f8361460d565b925050600181019050613670565b5085935050505092915050565b60006136b5826145d4565b6136bf8185614649565b93506136ca836145ae565b8060005b838110156136fb5781516136e2888261359a565b97506136ed8361461a565b9250506001810190506136ce565b5085935050505092915050565b613711816146ab565b82525050565b6000613722826145df565b61372c818561465a565b935061373c81856020860161471c565b6137458161474f565b840191505092915050565b600061375b826145df565b613765818561466b565b935061377581856020860161471c565b80840191505092915050565b600061378c826145f5565b6137968185614676565b93506137a681856020860161471c565b6137af8161474f565b840191505092915050565b60006137c5826145ea565b6137cf8185614676565b93506137df81856020860161471c565b6137e88161474f565b840191505092915050565b6000613800601c83614676565b91507f4665652076616c75652073686f756c6420626520706f736974697665000000006000830152602082019050919050565b6000613840602b83614676565b91507f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008301527f74206f6620626f756e64730000000000000000000000000000000000000000006020830152604082019050919050565b60006138a6603283614676565b91507f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008301527f63656976657220696d706c656d656e74657200000000000000000000000000006020830152604082019050919050565b600061390c602683614676565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613972601c83614676565b91507f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006000830152602082019050919050565b60006139b2602483614676565b91507f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008301527f72657373000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a18601983614676565b91507f4552433732313a20617070726f766520746f2063616c6c6572000000000000006000830152602082019050919050565b6000613a58602c83614676565b91507f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008301527f697374656e7420746f6b656e00000000000000000000000000000000000000006020830152604082019050919050565b6000613abe603883614676565b91507f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008301527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006020830152604082019050919050565b6000613b24602a83614676565b91507f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008301527f726f2061646472657373000000000000000000000000000000000000000000006020830152604082019050919050565b6000613b8a602983614676565b91507f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008301527f656e7420746f6b656e00000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bf0602083614676565b91507f4552433732313a206d696e7420746f20746865207a65726f20616464726573736000830152602082019050919050565b6000613c30602c83614676565b91507f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008301527f697374656e7420746f6b656e00000000000000000000000000000000000000006020830152604082019050919050565b6000613c96602c83614676565b91507f4552433732314d657461646174613a2055524920736574206f66206e6f6e657860008301527f697374656e7420746f6b656e00000000000000000000000000000000000000006020830152604082019050919050565b6000613cfc602083614676565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613d3c602983614676565b91507f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008301527f73206e6f74206f776e00000000000000000000000000000000000000000000006020830152604082019050919050565b6000613da2602f83614676565b91507f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008301527f6e6578697374656e7420746f6b656e00000000000000000000000000000000006020830152604082019050919050565b6000613e08602183614676565b91507f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008301527f72000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613e6e603183614676565b91507f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008301527f776e6572206e6f7220617070726f7665640000000000000000000000000000006020830152604082019050919050565b6000613ed4602c83614676565b91507f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008301527f7574206f6620626f756e647300000000000000000000000000000000000000006020830152604082019050919050565b6000613f3a602583614676565b91507f4552433732313a206275726e206f6620746f6b656e2074686174206973206e6f60008301527f74206f776e0000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613fa0601b83614676565b91507f526563697069656e742073686f756c642062652070726573656e7400000000006000830152602082019050919050565b6000613fe0603083614676565b91507f4552433732314275726e61626c653a2063616c6c6572206973206e6f74206f7760008301527f6e6572206e6f7220617070726f766564000000000000000000000000000000006020830152604082019050919050565b61404281614703565b82525050565b61405181614703565b82525050565b60006140638284613750565b915081905092915050565b600060208201905061408360008301846135df565b92915050565b600060808201905061409e60008301876135c1565b6140ab60208301866135df565b6140b86040830185614048565b81810360608301526140ca8184613717565b905095945050505050565b60006040820190506140ea60008301856135c1565b6140f76020830184614048565b9392505050565b60006020820190508181036000830152614118818461364c565b905092915050565b6000602082019050818103600083015261413a81846136aa565b905092915050565b60006020820190506141576000830184613708565b92915050565b6000602082019050818103600083015261417781846137ba565b905092915050565b600060208201905081810360008301526141998184613781565b905092915050565b600060208201905081810360008301526141ba816137f3565b9050919050565b600060208201905081810360008301526141da81613833565b9050919050565b600060208201905081810360008301526141fa81613899565b9050919050565b6000602082019050818103600083015261421a816138ff565b9050919050565b6000602082019050818103600083015261423a81613965565b9050919050565b6000602082019050818103600083015261425a816139a5565b9050919050565b6000602082019050818103600083015261427a81613a0b565b9050919050565b6000602082019050818103600083015261429a81613a4b565b9050919050565b600060208201905081810360008301526142ba81613ab1565b9050919050565b600060208201905081810360008301526142da81613b17565b9050919050565b600060208201905081810360008301526142fa81613b7d565b9050919050565b6000602082019050818103600083015261431a81613be3565b9050919050565b6000602082019050818103600083015261433a81613c23565b9050919050565b6000602082019050818103600083015261435a81613c89565b9050919050565b6000602082019050818103600083015261437a81613cef565b9050919050565b6000602082019050818103600083015261439a81613d2f565b9050919050565b600060208201905081810360008301526143ba81613d95565b9050919050565b600060208201905081810360008301526143da81613dfb565b9050919050565b600060208201905081810360008301526143fa81613e61565b9050919050565b6000602082019050818103600083015261441a81613ec7565b9050919050565b6000602082019050818103600083015261443a81613f2d565b9050919050565b6000602082019050818103600083015261445a81613f93565b9050919050565b6000602082019050818103600083015261447a81613fd3565b9050919050565b60006020820190506144966000830184614048565b92915050565b60006060820190506144b16000830186614048565b81810360208301526144c381856135ee565b905081810360408301526144d781846136aa565b9050949350505050565b6000604051905081810181811067ffffffffffffffff8211171561450457600080fd5b8060405250919050565b600067ffffffffffffffff82111561452557600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561454d57600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff82111561457957600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000614692826146e3565b9050919050565b60006146a4826146e3565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b8381101561473a57808201518184015260208101905061471f565b83811115614749576000848401525b50505050565b6000601f19601f8301169050919050565b61476981614687565b811461477457600080fd5b50565b61478081614699565b811461478b57600080fd5b50565b614797816146ab565b81146147a257600080fd5b50565b6147ae816146b7565b81146147b957600080fd5b50565b6147c581614703565b81146147d057600080fd5b5056fea365627a7a72315820fe8b88e5b093d86259a3390c69df5896e2df56628a11052a45fc63df45cece2a6c6578706572696d656e74616cf564736f6c6343000511004068747470733a2f2f6170692d6d61696e6e65742e72617269626c652e636f6d2f636f6e74726163744d657461646174612f7b616464726573737d68747470733a2f2f676174657761792e70696e6174612e636c6f75642f697066732f

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101e55760003560e01c8063715018a61161010f578063b88d4fde116100a2578063e8a3d48511610071578063e8a3d485146105a3578063e985e9c5146105c1578063f2fde38b146105f1578063f88190b11461060d576101e5565b8063b88d4fde14610509578063b9c4d9fb14610525578063c0ac998314610555578063c87b56dd14610573576101e5565b8063938e3d7b116100de578063938e3d7b1461049757806395d89b41146104b357806399e0dd7c146104d1578063a22cb465146104ed576101e5565b8063715018a6146104335780637ba3c4581461043d5780638da5cb5b1461045b5780638f32d59b14610479576101e5565b806323b872dd116101875780634f6ccce7116101565780634f6ccce7146103725780636308f1cd146103a25780636352211e146103d357806370a0823114610403576101e5565b806323b872dd146102ee5780632f745c591461030a57806342842e0e1461033a57806342966c6814610356576101e5565b8063095ea7b3116101c3578063095ea7b3146102685780630ebd4c7f14610284578063162094c4146102b457806318160ddd146102d0576101e5565b806301ffc9a7146101ea57806306fdde031461021a578063081812fc14610238575b600080fd5b61020460048036036101ff91908101906133b2565b610629565b6040516102119190614142565b60405180910390f35b610222610691565b60405161022f919061415d565b60405180910390f35b610252600480360361024d91908101906134b1565b61072f565b60405161025f919061406e565b60405180910390f35b610282600480360361027d9190810190613376565b6107b4565b005b61029e600480360361029991908101906134b1565b61096f565b6040516102ab9190614120565b60405180910390f35b6102ce60048036036102c991908101906134da565b610ac9565b005b6102d8610b1e565b6040516102e59190614481565b60405180910390f35b61030860048036036103039190810190613270565b610b2b565b005b610324600480360361031f9190810190613376565b610b8b565b6040516103319190614481565b60405180910390f35b610354600480360361034f9190810190613270565b610c34565b005b610370600480360361036b91908101906134b1565b610c54565b005b61038c600480360361038791908101906134b1565b610cb0565b6040516103999190614481565b60405180910390f35b6103bc60048036036103b7919081019061352e565b610d1a565b6040516103ca9291906140d5565b60405180910390f35b6103ed60048036036103e891908101906134b1565b610d78565b6040516103fa919061406e565b60405180910390f35b61041d6004803603610418919081019061320b565b610e2a565b60405161042a9190614481565b60405180910390f35b61043b610ee9565b005b610445610fef565b6040516104529190614481565b60405180910390f35b610463610ff5565b604051610470919061406e565b60405180910390f35b61048161101e565b60405161048e9190614142565b60405180910390f35b6104b160048036036104ac9190810190613404565b61107c565b005b6104bb6110cf565b6040516104c8919061415d565b60405180910390f35b6104eb60048036036104e69190810190613404565b61116d565b005b6105076004803603610502919081019061333a565b6111c0565b005b610523600480360361051e91908101906132bf565b611341565b005b61053f600480360361053a91908101906134b1565b6113a3565b60405161054c91906140fe565b60405180910390f35b61055d61152b565b60405161056a919061415d565b60405180910390f35b61058d600480360361058891908101906134b1565b6115c9565b60405161059a919061417f565b60405180910390f35b6105ab611623565b6040516105b8919061415d565b60405180910390f35b6105db60048036036105d69190810190613234565b6116c1565b6040516105e89190614142565b60405180910390f35b61060b6004803603610606919081019061320b565b611755565b005b61062760048036036106229190810190613445565b6117a8565b005b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b600d8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107275780601f106106fc57610100808354040283529160200191610727565b820191906000526020600020905b81548152906001019060200180831161070a57829003601f168201915b505050505081565b600061073a8261181c565b610779576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090614321565b60405180910390fd5b6003600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006107bf82610d78565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610830576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610827906143c1565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1661084f61188e565b73ffffffffffffffffffffffffffffffffffffffff16148061087e575061087d8161087861188e565b6116c1565b5b6108bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b4906142a1565b60405180910390fd5b826003600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b606080600f6000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610a3757838290600052602060002090600202016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481525050815260200190600101906109a5565b50505050905060608151604051908082528060200260200182016040528015610a6f5781602001602082028038833980820191505090505b50905060008090505b8251811015610abe57828181518110610a8d57fe5b602002602001015160200151828281518110610aa557fe5b6020026020010181815250508080600101915050610a78565b508092505050919050565b610ad161101e565b610b10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0790614361565b60405180910390fd5b610b1a8282611896565b5050565b6000600b80549050905090565b610b3c610b3661188e565b826118ec565b610b7b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b72906143e1565b60405180910390fd5b610b868383836119ca565b505050565b6000610b9683610e2a565b8210610bd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bce906141c1565b60405180910390fd5b600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110610c2157fe5b9060005260206000200154905092915050565b610c4f83838360405180602001604052806000815250611341565b505050565b610c65610c5f61188e565b826118ec565b610ca4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c9b90614461565b60405180910390fd5b610cad816119ee565b50565b6000610cba610b1e565b8210610cfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cf290614401565b60405180910390fd5b600b8281548110610d0857fe5b90600052602060002001549050919050565b600f6020528160005260406000208181548110610d3357fe5b9060005260206000209060020201600091509150508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154905082565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610e21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e18906142e1565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610e9b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e92906142c1565b60405180910390fd5b610ee2600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611a03565b9050919050565b610ef161101e565b610f30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2790614361565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60105481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661106061188e565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b61108461101e565b6110c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ba90614361565b60405180910390fd5b6110cc81611a11565b50565b600e8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156111655780601f1061113a57610100808354040283529160200191611165565b820191906000526020600020905b81548152906001019060200180831161114857829003601f168201915b505050505081565b61117561101e565b6111b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ab90614361565b60405180910390fd5b6111bd81611a2b565b50565b6111c861188e565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611236576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122d90614261565b60405180910390fd5b806005600061124361188e565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff166112f061188e565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516113359190614142565b60405180910390a35050565b61135261134c61188e565b836118ec565b611391576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611388906143e1565b60405180910390fd5b61139d84848484611a45565b50505050565b606080600f6000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561146b57838290600052602060002090600202016040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481525050815260200190600101906113d9565b505050509050606081516040519080825280602002602001820160405280156114a35781602001602082028038833980820191505090505b50905060008090505b8251811015611520578281815181106114c157fe5b6020026020010151600001518282815181106114d957fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080806001019150506114ac565b508092505050919050565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156115c15780601f10611596576101008083540402835291602001916115c1565b820191906000526020600020905b8154815290600101906020018083116115a457829003601f168201915b505050505081565b60606115d48261181c565b611613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161160a906143a1565b60405180910390fd5b61161c82611aa1565b9050919050565b60068054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156116b95780601f1061168e576101008083540402835291602001916116b9565b820191906000526020600020905b81548152906001019060200180831161169c57829003601f168201915b505050505081565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b61175d61101e565b61179c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161179390614361565b60405180910390fd5b6117a581611c02565b50565b6117b061101e565b6117ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e690614361565b60405180910390fd5b6001601054016010819055506000601054905061180d338284611d30565b6118178184611896565b505050565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415915050919050565b600033905090565b61189f8261181c565b6118de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118d590614341565b60405180910390fd5b6118e88282612024565b5050565b60006118f78261181c565b611936576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192d90614281565b60405180910390fd5b600061194183610d78565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806119b057508373ffffffffffffffffffffffffffffffffffffffff166119988461072f565b73ffffffffffffffffffffffffffffffffffffffff16145b806119c157506119c081856116c1565b5b91505092915050565b6119d5838383612050565b6119df838261227f565b6119e9828261241d565b505050565b611a006119fa82610d78565b826124e4565b50565b600081600001549050919050565b8060069080519060200190611a27929190612efd565b5050565b8060079080519060200190611a41929190612efd565b5050565b611a508484846119ca565b611a5c848484846124fb565b611a9b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a92906141e1565b60405180910390fd5b50505050565b6060611bfb600860008481526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611b4d5780601f10611b2257610100808354040283529160200191611b4d565b820191906000526020600020905b815481529060010190602001808311611b3057829003601f168201915b505050505060078054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611be85780601f10611bbd57610100808354040283529160200191611be8565b820191906000526020600020905b815481529060010190602001808311611bcb57829003601f168201915b50505050506126f590919063ffffffff16565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6990614201565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b611d3a8383612838565b60608151604051908082528060200260200182016040528015611d6c5781602001602082028038833980820191505090505b50905060608251604051908082528060200260200182016040528015611da15781602001602082028038833980820191505090505b50905060008090505b8351811015611fd657600073ffffffffffffffffffffffffffffffffffffffff16848281518110611dd757fe5b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff161415611e3a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e3190614441565b60405180910390fd5b6000848281518110611e4857fe5b6020026020010151602001511415611e95576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8c906141a1565b60405180910390fd5b600f6000868152602001908152602001600020848281518110611eb457fe5b60200260200101519080600181540180825580915050906001820390600052602060002090600202016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155505050838181518110611f4757fe5b602002602001015160000151838281518110611f5f57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050838181518110611fa557fe5b602002602001015160200151828281518110611fbd57fe5b6020026020010181815250508080600101915050611daa565b5060008351111561201d577f99aba1d63749cfd5ad1afda7c4663840924d54eb5f005bbbeadedc6ec13674b28483836040516120149392919061449c565b60405180910390a15b5050505050565b8060086000848152602001908152602001600020908051906020019061204b929190612efd565b505050565b8273ffffffffffffffffffffffffffffffffffffffff1661207082610d78565b73ffffffffffffffffffffffffffffffffffffffff16146120c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120bd90614381565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612136576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161212d90614241565b60405180910390fd5b61213f81612859565b612186600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612917565b6121cd600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061293a565b816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60006122d76001600960008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905061295090919063ffffffff16565b90506000600a60008481526020019081526020016000205490508181146123c4576000600960008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838154811061234457fe5b9060005260206000200154905080600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838154811061239c57fe5b906000526020600020018190555081600a600083815260200190815260200160002081905550505b600960008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054809190600190036124169190612f7d565b5050505050565b600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050600a600083815260200190815260200160002081905550600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190806001815401808255809150509060018203906000526020600020016000909192909190915055505050565b6124ee828261299a565b6124f7816129d4565b5050565b600061251c8473ffffffffffffffffffffffffffffffffffffffff16612a26565b61252957600190506126ed565b600060608573ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1663150b7a02905060e01b61256d61188e565b8988886040516024016125839493929190614089565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516125ed9190614057565b6000604051808303816000865af19150503d806000811461262a576040519150601f19603f3d011682016040523d82523d6000602084013e61262f565b606091505b5091509150816126875760008151111561264c5780518082602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161267e906141e1565b60405180910390fd5b60008180602001905161269d91908101906133db565b905063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161493505050505b949350505050565b6060808390506060839050606081518351016040519080825280601f01601f1916602001820160405280156127395781602001600182028038833980820191505090505b509050600080905060008090505b84518110156127b55784818151811061275c57fe5b602001015160f81c60f81b83838060010194508151811061277957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050612747565b5060008090505b835181101561282a578381815181106127d157fe5b602001015160f81c60f81b8383806001019450815181106127ee57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506127bc565b508194505050505092915050565b6128428282612a71565b61284c828261241d565b61285581612c23565b5050565b600073ffffffffffffffffffffffffffffffffffffffff166003600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146129145760006003600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b61292f6001826000015461295090919063ffffffff16565b816000018190555050565b6001816000016000828254019250508190555050565b600061299283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612c6f565b905092915050565b6129a48282612cca565b6129ae828261227f565b6000600a6000838152602001908152602001600020819055506129d081612e43565b5050565b60006008600083815260200190815260200160002080546001816001161561010002031660029004905014612a2357600860008281526020019081526020016000206000612a229190612fa9565b5b50565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f9150808214158015612a6857506000801b8214155b92505050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ad890614301565b60405180910390fd5b612aea8161181c565b15612b2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b2190614221565b60405180910390fd5b816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612bc3600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061293a565b808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600b80549050600c600083815260200190815260200160002081905550600b81908060018154018082558091505090600182039060005260206000200160009091929091909150555050565b6000838311158290612cb7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cae919061417f565b60405180910390fd5b5060008385039050809150509392505050565b8173ffffffffffffffffffffffffffffffffffffffff16612cea82610d78565b73ffffffffffffffffffffffffffffffffffffffff1614612d40576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d3790614421565b60405180910390fd5b612d4981612859565b612d90600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612917565b60006002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b6000612e5e6001600b8054905061295090919063ffffffff16565b90506000600c60008481526020019081526020016000205490506000600b8381548110612e8757fe5b9060005260206000200154905080600b8381548110612ea257fe5b906000526020600020018190555081600c600083815260200190815260200160002081905550600b805480919060019003612edd9190612f7d565b506000600c60008681526020019081526020016000208190555050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612f3e57805160ff1916838001178555612f6c565b82800160010185558215612f6c579182015b82811115612f6b578251825591602001919060010190612f50565b5b509050612f799190612ff1565b5090565b815481835581811115612fa457818360005260206000209182019101612fa39190612ff1565b5b505050565b50805460018160011615610100020316600290046000825580601f10612fcf5750612fee565b601f016020900490600052602060002090810190612fed9190612ff1565b5b50565b61301391905b8082111561300f576000816000905550600101612ff7565b5090565b90565b60008135905061302581614760565b92915050565b60008135905061303a81614777565b92915050565b600082601f83011261305157600080fd5b813561306461305f8261450e565b6144e1565b9150818183526020840193506020810190508385604084028201111561308957600080fd5b60005b838110156130b9578161309f88826131aa565b84526020840193506040830192505060018101905061308c565b5050505092915050565b6000813590506130d28161478e565b92915050565b6000813590506130e7816147a5565b92915050565b6000815190506130fc816147a5565b92915050565b600082601f83011261311357600080fd5b813561312661312182614536565b6144e1565b9150808252602083016020830185838301111561314257600080fd5b61314d83828461470d565b50505092915050565b600082601f83011261316757600080fd5b813561317a61317582614562565b6144e1565b9150808252602083016020830185838301111561319657600080fd5b6131a183828461470d565b50505092915050565b6000604082840312156131bc57600080fd5b6131c660406144e1565b905060006131d68482850161302b565b60008301525060206131ea848285016131f6565b60208301525092915050565b600081359050613205816147bc565b92915050565b60006020828403121561321d57600080fd5b600061322b84828501613016565b91505092915050565b6000806040838503121561324757600080fd5b600061325585828601613016565b925050602061326685828601613016565b9150509250929050565b60008060006060848603121561328557600080fd5b600061329386828701613016565b93505060206132a486828701613016565b92505060406132b5868287016131f6565b9150509250925092565b600080600080608085870312156132d557600080fd5b60006132e387828801613016565b94505060206132f487828801613016565b9350506040613305878288016131f6565b925050606085013567ffffffffffffffff81111561332257600080fd5b61332e87828801613102565b91505092959194509250565b6000806040838503121561334d57600080fd5b600061335b85828601613016565b925050602061336c858286016130c3565b9150509250929050565b6000806040838503121561338957600080fd5b600061339785828601613016565b92505060206133a8858286016131f6565b9150509250929050565b6000602082840312156133c457600080fd5b60006133d2848285016130d8565b91505092915050565b6000602082840312156133ed57600080fd5b60006133fb848285016130ed565b91505092915050565b60006020828403121561341657600080fd5b600082013567ffffffffffffffff81111561343057600080fd5b61343c84828501613156565b91505092915050565b6000806040838503121561345857600080fd5b600083013567ffffffffffffffff81111561347257600080fd5b61347e85828601613156565b925050602083013567ffffffffffffffff81111561349b57600080fd5b6134a785828601613040565b9150509250929050565b6000602082840312156134c357600080fd5b60006134d1848285016131f6565b91505092915050565b600080604083850312156134ed57600080fd5b60006134fb858286016131f6565b925050602083013567ffffffffffffffff81111561351857600080fd5b61352485828601613156565b9150509250929050565b6000806040838503121561354157600080fd5b600061354f858286016131f6565b9250506020613560858286016131f6565b9150509250929050565b600061357683836135b2565b60208301905092915050565b600061358e83836135d0565b60208301905092915050565b60006135a68383614039565b60208301905092915050565b6135bb81614699565b82525050565b6135ca81614699565b82525050565b6135d981614687565b82525050565b6135e881614687565b82525050565b60006135f9826145be565b6136038185614627565b935061360e8361458e565b8060005b8381101561363f5781516136268882613582565b975061363183614600565b925050600181019050613612565b5085935050505092915050565b6000613657826145c9565b6136618185614638565b935061366c8361459e565b8060005b8381101561369d578151613684888261356a565b975061368f8361460d565b925050600181019050613670565b5085935050505092915050565b60006136b5826145d4565b6136bf8185614649565b93506136ca836145ae565b8060005b838110156136fb5781516136e2888261359a565b97506136ed8361461a565b9250506001810190506136ce565b5085935050505092915050565b613711816146ab565b82525050565b6000613722826145df565b61372c818561465a565b935061373c81856020860161471c565b6137458161474f565b840191505092915050565b600061375b826145df565b613765818561466b565b935061377581856020860161471c565b80840191505092915050565b600061378c826145f5565b6137968185614676565b93506137a681856020860161471c565b6137af8161474f565b840191505092915050565b60006137c5826145ea565b6137cf8185614676565b93506137df81856020860161471c565b6137e88161474f565b840191505092915050565b6000613800601c83614676565b91507f4665652076616c75652073686f756c6420626520706f736974697665000000006000830152602082019050919050565b6000613840602b83614676565b91507f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008301527f74206f6620626f756e64730000000000000000000000000000000000000000006020830152604082019050919050565b60006138a6603283614676565b91507f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008301527f63656976657220696d706c656d656e74657200000000000000000000000000006020830152604082019050919050565b600061390c602683614676565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613972601c83614676565b91507f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006000830152602082019050919050565b60006139b2602483614676565b91507f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008301527f72657373000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a18601983614676565b91507f4552433732313a20617070726f766520746f2063616c6c6572000000000000006000830152602082019050919050565b6000613a58602c83614676565b91507f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008301527f697374656e7420746f6b656e00000000000000000000000000000000000000006020830152604082019050919050565b6000613abe603883614676565b91507f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008301527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006020830152604082019050919050565b6000613b24602a83614676565b91507f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008301527f726f2061646472657373000000000000000000000000000000000000000000006020830152604082019050919050565b6000613b8a602983614676565b91507f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008301527f656e7420746f6b656e00000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bf0602083614676565b91507f4552433732313a206d696e7420746f20746865207a65726f20616464726573736000830152602082019050919050565b6000613c30602c83614676565b91507f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008301527f697374656e7420746f6b656e00000000000000000000000000000000000000006020830152604082019050919050565b6000613c96602c83614676565b91507f4552433732314d657461646174613a2055524920736574206f66206e6f6e657860008301527f697374656e7420746f6b656e00000000000000000000000000000000000000006020830152604082019050919050565b6000613cfc602083614676565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613d3c602983614676565b91507f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008301527f73206e6f74206f776e00000000000000000000000000000000000000000000006020830152604082019050919050565b6000613da2602f83614676565b91507f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008301527f6e6578697374656e7420746f6b656e00000000000000000000000000000000006020830152604082019050919050565b6000613e08602183614676565b91507f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008301527f72000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613e6e603183614676565b91507f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008301527f776e6572206e6f7220617070726f7665640000000000000000000000000000006020830152604082019050919050565b6000613ed4602c83614676565b91507f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008301527f7574206f6620626f756e647300000000000000000000000000000000000000006020830152604082019050919050565b6000613f3a602583614676565b91507f4552433732313a206275726e206f6620746f6b656e2074686174206973206e6f60008301527f74206f776e0000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613fa0601b83614676565b91507f526563697069656e742073686f756c642062652070726573656e7400000000006000830152602082019050919050565b6000613fe0603083614676565b91507f4552433732314275726e61626c653a2063616c6c6572206973206e6f74206f7760008301527f6e6572206e6f7220617070726f766564000000000000000000000000000000006020830152604082019050919050565b61404281614703565b82525050565b61405181614703565b82525050565b60006140638284613750565b915081905092915050565b600060208201905061408360008301846135df565b92915050565b600060808201905061409e60008301876135c1565b6140ab60208301866135df565b6140b86040830185614048565b81810360608301526140ca8184613717565b905095945050505050565b60006040820190506140ea60008301856135c1565b6140f76020830184614048565b9392505050565b60006020820190508181036000830152614118818461364c565b905092915050565b6000602082019050818103600083015261413a81846136aa565b905092915050565b60006020820190506141576000830184613708565b92915050565b6000602082019050818103600083015261417781846137ba565b905092915050565b600060208201905081810360008301526141998184613781565b905092915050565b600060208201905081810360008301526141ba816137f3565b9050919050565b600060208201905081810360008301526141da81613833565b9050919050565b600060208201905081810360008301526141fa81613899565b9050919050565b6000602082019050818103600083015261421a816138ff565b9050919050565b6000602082019050818103600083015261423a81613965565b9050919050565b6000602082019050818103600083015261425a816139a5565b9050919050565b6000602082019050818103600083015261427a81613a0b565b9050919050565b6000602082019050818103600083015261429a81613a4b565b9050919050565b600060208201905081810360008301526142ba81613ab1565b9050919050565b600060208201905081810360008301526142da81613b17565b9050919050565b600060208201905081810360008301526142fa81613b7d565b9050919050565b6000602082019050818103600083015261431a81613be3565b9050919050565b6000602082019050818103600083015261433a81613c23565b9050919050565b6000602082019050818103600083015261435a81613c89565b9050919050565b6000602082019050818103600083015261437a81613cef565b9050919050565b6000602082019050818103600083015261439a81613d2f565b9050919050565b600060208201905081810360008301526143ba81613d95565b9050919050565b600060208201905081810360008301526143da81613dfb565b9050919050565b600060208201905081810360008301526143fa81613e61565b9050919050565b6000602082019050818103600083015261441a81613ec7565b9050919050565b6000602082019050818103600083015261443a81613f2d565b9050919050565b6000602082019050818103600083015261445a81613f93565b9050919050565b6000602082019050818103600083015261447a81613fd3565b9050919050565b60006020820190506144966000830184614048565b92915050565b60006060820190506144b16000830186614048565b81810360208301526144c381856135ee565b905081810360408301526144d781846136aa565b9050949350505050565b6000604051905081810181811067ffffffffffffffff8211171561450457600080fd5b8060405250919050565b600067ffffffffffffffff82111561452557600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561454d57600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff82111561457957600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000614692826146e3565b9050919050565b60006146a4826146e3565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b8381101561473a57808201518184015260208101905061471f565b83811115614749576000848401525b50505050565b6000601f19601f8301169050919050565b61476981614687565b811461477457600080fd5b50565b61478081614699565b811461478b57600080fd5b50565b614797816146ab565b81146147a257600080fd5b50565b6147ae816146b7565b81146147b957600080fd5b50565b6147c581614703565b81146147d057600080fd5b5056fea365627a7a72315820fe8b88e5b093d86259a3390c69df5896e2df56628a11052a45fc63df45cece2a6c6578706572696d656e74616cf564736f6c63430005110040

Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.