ETH Price: $3,908.12 (+0.39%)

Token

WeTrust Token of Appreciation (WTOA)
 

Overview

Max Total Supply

76 WTOA

Holders

44

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 WTOA
0xa7f3dfed2bcf7b35a8824e11ae8f723650edfb58
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
SpringNFT

Compiler Version
v0.4.24+commit.e67f0147

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2018-09-25
*/

pragma solidity ^0.4.24;

/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
///  Note: the ERC-165 identifier for this interface is 0x80ac58cd.
interface ERC721 /* is ERC165 */ {
    /// @dev This emits when ownership of any NFT changes by any mechanism.
    ///  This event emits when NFTs are created (`from` == 0) and destroyed
    ///  (`to` == 0). Exception: during contract creation, any number of NFTs
    ///  may be created and assigned without emitting Transfer. At the time of
    ///  any transfer, the approved address for that NFT (if any) is reset to none.
    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);

    /// @dev This emits when the approved address for an NFT is changed or
    ///  reaffirmed. The zero address indicates there is no approved address.
    ///  When a Transfer event emits, this also indicates that the approved
    ///  address for that NFT (if any) is reset to none.
    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);

    /// @dev This emits when an operator is enabled or disabled for an owner.
    ///  The operator can manage all NFTs of the owner.
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

    /// @notice Count all NFTs assigned to an owner
    /// @dev NFTs assigned to the zero address are considered invalid, and this
    ///  function throws for queries about the zero address.
    /// @param _owner An address for whom to query the balance
    /// @return The number of NFTs owned by `_owner`, possibly zero
    function balanceOf(address _owner) external view returns (uint256);

    /// @notice Find the owner of an NFT
    /// @dev NFTs assigned to zero address are considered invalid, and queries
    ///  about them do throw.
    /// @param _tokenId The identifier for an NFT
    /// @return The address of the owner of the NFT
    function ownerOf(uint256 _tokenId) external view returns (address);

    /// @notice Transfers the ownership of an NFT from one address to another address
    /// @dev Throws unless `msg.sender` is the current owner, an authorized
    ///  operator, or the approved address for this NFT. Throws if `_from` is
    ///  not the current owner. Throws if `_to` is the zero address. Throws if
    ///  `_tokenId` is not a valid NFT. When transfer is complete, this function
    ///  checks if `_to` is a smart contract (code size > 0). If so, it calls
    ///  `onERC721Received` on `_to` and throws if the return value is not
    ///  `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    /// @param data Additional data with no specified format, sent in call to `_to`
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external;

    /// @notice Transfers the ownership of an NFT from one address to another address
    /// @dev This works identically to the other function with an extra data parameter,
    ///  except this function just sets data to "".
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external;

    /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
    ///  TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
    ///  THEY MAY BE PERMANENTLY LOST
    /// @dev Throws unless `msg.sender` is the current owner, an authorized
    ///  operator, or the approved address for this NFT. Throws if `_from` is
    ///  not the current owner. Throws if `_to` is the zero address. Throws if
    ///  `_tokenId` is not a valid NFT.
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    function transferFrom(address _from, address _to, uint256 _tokenId) external;

    /// @notice Change or reaffirm the approved address for an NFT
    /// @dev The zero address indicates there is no approved address.
    ///  Throws unless `msg.sender` is the current NFT owner, or an authorized
    ///  operator of the current owner.
    /// @param _approved The new approved NFT controller
    /// @param _tokenId The NFT to approve
    function approve(address _approved, uint256 _tokenId) external;

    /// @notice Enable or disable approval for a third party ("operator") to manage
    ///  all of `msg.sender`'s assets
    /// @dev Emits the ApprovalForAll event. The contract MUST allow
    ///  multiple operators per owner.
    /// @param _operator Address to add to the set of authorized operators
    /// @param _approved True if the operator is approved, false to revoke approval
    function setApprovalForAll(address _operator, bool _approved) external;

    /// @notice Get the approved address for a single NFT
    /// @dev Throws if `_tokenId` is not a valid NFT.
    /// @param _tokenId The NFT to find the approved address for
    /// @return The approved address for this NFT, or the zero address if there is none
    function getApproved(uint256 _tokenId) external view returns (address);

    /// @notice Query if an address is an authorized operator for another address
    /// @param _owner The address that owns the NFTs
    /// @param _operator The address that acts on behalf of the owner
    /// @return True if `_operator` is an approved operator for `_owner`, false otherwise
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}

interface ERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
///  Note: the ERC-165 identifier for this interface is 0x780e9d63.
interface ERC721Enumerable /* is ERC721 */ {
    /// @notice Count NFTs tracked by this contract
    /// @return A count of valid NFTs tracked by this contract, where each one of
    ///  them has an assigned and queryable owner not equal to the zero address
    function totalSupply() external view returns (uint256);

    /// @notice Enumerate valid NFTs
    /// @dev Throws if `_index` >= `totalSupply()`.
    /// @param _index A counter less than `totalSupply()`
    /// @return The token identifier for the `_index`th NFT,
    ///  (sort order not specified)
    function tokenByIndex(uint256 _index) external view returns (uint256);

    /// @notice Enumerate NFTs assigned to an owner
    /// @dev Throws if `_index` >= `balanceOf(_owner)` or if
    ///  `_owner` is the zero address, representing invalid NFTs.
    /// @param _owner An address where we are interested in NFTs owned by them
    /// @param _index A counter less than `balanceOf(_owner)`
    /// @return The token identifier for the `_index`th NFT assigned to `_owner`,
    ///   (sort order not specified)
    function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
}

/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
///  Note: the ERC-165 identifier for this interface is 0x5b5e139f.
interface ERC721Metadata /* is ERC721 */ {
    /// @notice A descriptive name for a collection of NFTs in this contract
    function name() external view returns (string _name);

    /// @notice An abbreviated name for NFTs in this contract
    function symbol() external view returns (string _symbol);

    /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
    /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
    ///  3986. The URI may point to a JSON file that conforms to the "ERC721
    ///  Metadata JSON Schema".
    function tokenURI(uint256 _tokenId) external view returns (string);
}


/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
interface ERC721TokenReceiver {
    /// @notice Handle the receipt of an NFT
    /// @dev The ERC721 smart contract calls this function on the recipient
    ///  after a `transfer`. This function MAY throw to revert and reject the
    ///  transfer. Return of other than the magic value MUST result in the
    ///  transaction being reverted.
    ///  Note: the 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(keccak256("onERC721Received(address,address,uint256,bytes)"))`
    ///  unless throwing
    function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4);
}

/**
 * @dev Implementation of standard for detect smart contract interfaces.
 */
contract SupportsInterface {
    /**
     * @dev Mapping of supported intefraces.
     * @notice You must not set element 0xffffffff to true.
     */
    mapping(bytes4 => bool) internal supportedInterfaces;

    /**
     * @dev Contract constructor.
     */
    constructor()
    public
    {
        supportedInterfaces[0x01ffc9a7] = true; // ERC165
    }

    /**
     * @dev Function to check which interfaces are suported by this contract.
     * @param _interfaceID Id of the interface.
     */
    function supportsInterface(
        bytes4 _interfaceID
    )
    external
    view
    returns (bool)
    {
        return supportedInterfaces[_interfaceID];
    }

}

/**
 * @dev Utility library of inline functions on addresses.
 */
library AddressUtils {

    /**
     * @dev Returns whether the target address is a contract.
     * @param _addr Address to check.
     */
    function isContract(
        address _addr
    )
    internal
    view
    returns (bool)
    {
        uint256 size;

        /**
         * XXX Currently there is no better way to check if there is a contract in an address than to
         * check the size of the code at that address.
         * See https://ethereum.stackexchange.com/a/14016/36603 for more details about how this works.
         * TODO: Check this again before the Serenity release, because all addresses will be
         * contracts then.
         */
        assembly { size := extcodesize(_addr) } // solium-disable-line security/no-inline-assembly
        return size > 0;
    }

}

/**
 * @dev Implementation of ERC-721 non-fungible token standard specifically for WeTrust Spring.
 */
contract NFToken is ERC721, SupportsInterface, ERC721Metadata, ERC721Enumerable {
    using AddressUtils for address;

    ///////////////////////////
    // Constants
    //////////////////////////

    /**
     * @dev Magic value of a smart contract that can recieve NFT.
     * Equal to: bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")).
     */
    bytes4 constant MAGIC_ON_ERC721_RECEIVED = 0x150b7a02;

    //////////////////////////
    // Events
    //////////////////////////

    /**
     * @dev Emits when ownership of any NFT changes by any mechanism. This event emits when NFTs are
     * created (`from` == 0) and destroyed (`to` == 0). Exception: during contract creation, any
     * number of NFTs may be created and assigned without emitting Transfer. At the time of any
     * transfer, the approved address for that NFT (if any) is reset to none.
     * @param _from Sender of NFT (if address is zero address it indicates token creation).
     * @param _to Receiver of NFT (if address is zero address it indicates token destruction).
     * @param _tokenId The NFT that got transfered.
     */
    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);

    /**
     * @dev This emits when the approved address for an NFT is changed or reaffirmed. The zero
     * address indicates there is no approved address. When a Transfer event emits, this also
     * indicates that the approved address for that NFT (if any) is reset to none.
     * @param _owner Owner of NFT.
     * @param _approved Address that we are approving.
     * @param _tokenId NFT which we are approving.
     */
    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);

    /**
     * @dev This emits when an operator is enabled or disabled for an owner. The operator can manage
     * all NFTs of the owner.
     * @param _owner Owner of NFT.
     * @param _operator Address to which we are setting operator rights.
     * @param _approved Status of operator rights(true if operator rights are given and false if
     * revoked).
     */
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

    ////////////////////////////////
    // Modifiers
    ///////////////////////////////

    /**
     * @dev Guarantees that the msg.sender is an owner or operator of the given NFT.
     * @param _tokenId ID of the NFT to validate.
     */
    modifier canOperate(uint256 _tokenId) {
        address tokenOwner = nft[_tokenId].owner;
        require(tokenOwner == msg.sender || ownerToOperators[tokenOwner][msg.sender], "Sender is not an authorized operator of this token");
        _;
    }

    /**
     * @dev Guarantees that the msg.sender is allowed to transfer NFT.
     * @param _tokenId ID of the NFT to transfer.
     */
    modifier canTransfer(uint256 _tokenId) {
        address tokenOwner = nft[_tokenId].owner;
        require(
            tokenOwner == msg.sender ||
            getApproved(_tokenId) == msg.sender || ownerToOperators[tokenOwner][msg.sender],
            "Sender does not have permission to transfer this Token");

        _;
    }

    /**
     * @dev Check to make sure the address is not zero address
     * @param toTest The Address to make sure it's not zero address
     */
    modifier onlyNonZeroAddress(address toTest) {
        require(toTest != address(0), "Address must be non zero address");
        _;
    }

    /**
     * @dev Guarantees that no owner exists for the nft
     * @param nftId NFT to test
     */
    modifier noOwnerExists(uint256 nftId) {
        require(nft[nftId].owner == address(0), "Owner must not exist for this token");
        _;
    }

    /**
     * @dev Guarantees that an owner exists for the nft
     * @param nftId NFT to test
     */
    modifier ownerExists(uint256 nftId) {
        require(nft[nftId].owner != address(0), "Owner must exist for this token");
        _;
    }

    ///////////////////////////
    // Storage Variable
    //////////////////////////

    /**
     * @dev name of the NFT
     */
    string nftName = "WeTrust Nifty";

    /**
     * @dev NFT symbol
     */
    string nftSymbol = "SPRN";

    /**
     * @dev hostname to be used as base for tokenURI
     */
    string public hostname = "https://spring.wetrust.io/shiba/";

    /**
     * @dev A mapping from NFT ID to the address that owns it.
     */
    mapping (uint256 => NFT) public nft;

    /**
     * @dev List of NFTs
     */
    uint256[] nftList;

    /**
    * @dev Mapping from owner address to count of his tokens.
    */
    mapping (address => uint256[]) internal ownerToTokenList;

    /**
     * @dev Mapping from owner address to mapping of operator addresses.
     */
    mapping (address => mapping (address => bool)) internal ownerToOperators;

    struct NFT {
        address owner;
        address approval;
        bytes32 traits;
        uint16 edition;
        bytes4 nftType;
        bytes32 recipientId;
        uint256 createdAt;
    }

    ////////////////////////////////
    // Public Functions
    ///////////////////////////////

    /**
     * @dev Contract constructor.
     */
    constructor() public {
        supportedInterfaces[0x780e9d63] = true; // ERC721Enumerable
        supportedInterfaces[0x5b5e139f] = true; // ERC721MetaData
        supportedInterfaces[0x80ac58cd] = true; // ERC721
    }

    /**
     * @dev Returns the number of NFTs owned by `_owner`. NFTs assigned to the zero address are
     * considered invalid, and this function throws for queries about the zero address.
     * @param _owner Address for whom to query the balance.
     */
    function balanceOf(address _owner) onlyNonZeroAddress(_owner) public view returns (uint256) {
        return ownerToTokenList[_owner].length;
    }

    /**
     * @dev Returns the address of the owner of the NFT. NFTs assigned to zero address are considered
     * invalid, and queries about them do throw.
     * @param _tokenId The identifier for an NFT.
     */
    function ownerOf(uint256 _tokenId) ownerExists(_tokenId) external view returns (address _owner) {
        return nft[_tokenId].owner;
    }

    /**
     * @dev Transfers the ownership of an NFT from one address to another address.
     * @notice Throws unless `msg.sender` is the current owner, an authorized operator, or the
     * approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is
     * the zero address. Throws if `_tokenId` is not a valid NFT. When transfer is complete, this
     * function checks if `_to` is a smart contract (code size > 0). If so, it calls `onERC721Received`
     * on `_to` and throws if the return value is not `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`.
     * @param _from The current owner of the NFT.
     * @param _to The new owner.
     * @param _tokenId The NFT to transfer.
     * @param _data Additional data with no specified format, sent in call to `_to`.
     */
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes _data) external {
        _safeTransferFrom(_from, _to, _tokenId, _data);
    }

    /**
     * @dev Transfers the ownership of an NFT from one address to another address.
     * @notice This works identically to the other function with an extra data parameter, except this
     * function just sets data to ""
     * @param _from The current owner of the NFT.
     * @param _to The new owner.
     * @param _tokenId The NFT to transfer.
     */
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external {
        _safeTransferFrom(_from, _to, _tokenId, "");
    }

    /**
     * @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved
     * address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero
     * address. Throws if `_tokenId` is not a valid NFT.
     * @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else
     * they maybe be permanently lost.
     * @param _from The current owner of the NFT.
     * @param _to The new owner.
     * @param _tokenId The NFT to transfer.
     */
    function transferFrom(address _from, address _to, uint256 _tokenId)
        onlyNonZeroAddress(_to)
        canTransfer(_tokenId)
        ownerExists(_tokenId)
        external
    {

        address tokenOwner = nft[_tokenId].owner;
        require(tokenOwner == _from, "from address must be owner of tokenId");

        _transfer(_to, _tokenId);
    }

    /**
     * @dev Set or reaffirm the approved address for an NFT.
     * @notice The zero address indicates there is no approved address. Throws unless `msg.sender` is
     * the current NFT owner, or an authorized operator of the current owner.
     * @param _approved Address to be approved for the given NFT ID.
     * @param _tokenId ID of the token to be approved.
     */
    function approve(address _approved, uint256 _tokenId)
        canOperate(_tokenId)
        ownerExists(_tokenId)
        external
    {

        address tokenOwner = nft[_tokenId].owner;
        require(_approved != tokenOwner, "approved address cannot be owner of the token");

        nft[_tokenId].approval = _approved;
        emit Approval(tokenOwner, _approved, _tokenId);
    }

    /**
     * @dev Enables or disables approval for a third party ("operator") to manage all of
     * `msg.sender`'s assets. It also emits the ApprovalForAll event.
     * @notice This works even if sender doesn't own any tokens at the time.
     * @param _operator Address to add to the set of authorized operators.
     * @param _approved True if the operators is approved, false to revoke approval.
     */
    function setApprovalForAll(address _operator, bool _approved)
        onlyNonZeroAddress(_operator)
        external
    {

        ownerToOperators[msg.sender][_operator] = _approved;
        emit ApprovalForAll(msg.sender, _operator, _approved);
    }

    /**
     * @dev Get the approved address for a single NFT.
     * @notice Throws if `_tokenId` is not a valid NFT.
     * @param _tokenId ID of the NFT to query the approval of.
     */
    function getApproved(uint256 _tokenId)
        ownerExists(_tokenId)
        public view returns (address)
    {

        return nft[_tokenId].approval;
    }

    /**
     * @dev Checks if `_operator` is an approved operator for `_owner`.
     * @param _owner The address that owns the NFTs.
     * @param _operator The address that acts on behalf of the owner.
     */
    function isApprovedForAll(address _owner, address _operator)
        onlyNonZeroAddress(_owner)
        onlyNonZeroAddress(_operator)
        external view returns (bool)
    {

        return ownerToOperators[_owner][_operator];
    }

    /**
     * @dev return token list of owned by the owner
     * @param owner The address that owns the NFTs.
     */
    function getOwnedTokenList(address owner) view public returns(uint256[] tokenList) {
        return ownerToTokenList[owner];
    }

    /// @notice A descriptive name for a collection of NFTs in this contract
    function name() external view returns (string _name) {
        return nftName;
    }

    /// @notice An abbreviated name for NFTs in this contract
    function symbol() external view returns (string _symbol) {
        return nftSymbol;
    }

    /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
    /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
    ///  3986. The URI may point to a JSON file that conforms to the "ERC721
    ///  Metadata JSON Schema".
    function tokenURI(uint256 _tokenId) external view returns (string) {
        return appendUintToString(hostname, _tokenId);
    }

    /// @notice Count NFTs tracked by this contract
    /// @return A count of valid NFTs tracked by this contract, where each one of
    ///  them has an assigned and queryable owner not equal to the zero address
    function totalSupply() external view returns (uint256) {
        return nftList.length;
    }

    /// @notice Enumerate valid NFTs
    /// @dev Throws if `_index` >= `totalSupply()`.
    /// @param _index A counter less than `totalSupply()`
    /// @return The token identifier for the `_index`th NFT,
    ///  (sort order not specified)
    function tokenByIndex(uint256 _index) external view returns (uint256) {
        require(_index < nftList.length, "index out of range");
        return nftList[_index];
    }

    /// @notice Enumerate NFTs assigned to an owner
    /// @dev Throws if `_index` >= `balanceOf(_owner)` or if
    ///  `_owner` is the zero address, representing invalid NFTs.
    /// @param _owner An address where we are interested in NFTs owned by them
    /// @param _index A counter less than `balanceOf(_owner)`
    /// @return The token identifier for the `_index`th NFT assigned to `_owner`,
    ///   (sort order not specified)
    function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256) {
        require(_index < balanceOf(_owner), "index out of range");
        return ownerToTokenList[_owner][_index];
    }

    /////////////////////////////
    // Private Functions
    ////////////////////////////

    /**
     * @dev append uint to the end of string
     * @param inStr input string
     * @param v uint value v
     * credit goes to : https://ethereum.stackexchange.com/questions/10811/solidity-concatenate-uint-into-a-string
     */

    function appendUintToString(string inStr, uint v) pure internal returns (string str) {
        uint maxlength = 100;
        bytes memory reversed = new bytes(maxlength);
        uint i = 0;
        while (v != 0) {
            uint remainder = v % 10;
            v = v / 10;
            reversed[i++] = byte(48 + remainder);
        }
        bytes memory inStrb = bytes(inStr);
        bytes memory s = new bytes(inStrb.length + i);
        uint j;
        for (j = 0; j < inStrb.length; j++) {
            s[j] = inStrb[j];
        }
        for (j = 0; j < i; j++) {
            s[j + inStrb.length] = reversed[i - 1 - j];
        }
        str = string(s);
    }

    /**
     * @dev Actually preforms the transfer.
     * @notice Does NO checks.
     * @param _to Address of a new owner.
     * @param _tokenId The NFT that is being transferred.
     */
    function _transfer(address _to, uint256 _tokenId) private {
        address from = nft[_tokenId].owner;
        clearApproval(_tokenId);

        removeNFToken(from, _tokenId);
        addNFToken(_to, _tokenId);

        emit Transfer(from, _to, _tokenId);
    }

    function _safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes _data)
        onlyNonZeroAddress(_to)
        canTransfer(_tokenId)
        ownerExists(_tokenId)
        internal
    {
        address tokenOwner = nft[_tokenId].owner;
        require(tokenOwner == _from, "from address must be owner of tokenId");

        _transfer(_to, _tokenId);

        if (_to.isContract()) {
            bytes4 retval = ERC721TokenReceiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data);
            require(retval == MAGIC_ON_ERC721_RECEIVED, "reciever contract did not return the correct return value");
        }
    }

    /**
     * @dev Clears the current approval of a given NFT ID.
     * @param _tokenId ID of the NFT to be transferred.
     */
    function clearApproval(uint256 _tokenId) private {
        if(nft[_tokenId].approval != address(0))
        {
            delete nft[_tokenId].approval;
        }
    }

    /**
     * @dev Removes a NFT from owner.
     * @notice Use and override this function with caution. Wrong usage can have serious consequences.
     * @param _from Address from wich we want to remove the NFT.
     * @param _tokenId Which NFT we want to remove.
     */
    function removeNFToken(address _from, uint256 _tokenId) internal {
        require(nft[_tokenId].owner == _from, "from address must be owner of tokenId");
        uint256[] storage tokenList = ownerToTokenList[_from];
        assert(tokenList.length > 0);

        for (uint256 i = 0; i < tokenList.length; i++) {
            if (tokenList[i] == _tokenId) {
                tokenList[i] = tokenList[tokenList.length - 1];
                delete tokenList[tokenList.length - 1];
                tokenList.length--;
                break;
            }
        }
        delete nft[_tokenId].owner;
    }

    /**
     * @dev Assignes a new NFT to owner.
     * @notice Use and override this function with caution. Wrong usage can have serious consequences.
     * @param _to Address to wich we want to add the NFT.
     * @param _tokenId Which NFT we want to add.
     */
    function addNFToken(address _to, uint256 _tokenId)
        noOwnerExists(_tokenId)
        internal
    {
        nft[_tokenId].owner = _to;
        ownerToTokenList[_to].push(_tokenId);
    }

}


//@dev Implemention of NFT for WeTrust Spring
contract SpringNFT is NFToken{


    //////////////////////////////
    // Events
    /////////////////////////////
    event RecipientUpdate(bytes32 indexed recipientId, bytes32 updateId);

    //////////////////////////////
    // Modifiers
    /////////////////////////////

    /**
     * @dev Guarrentees that recipient Exists
     * @param id receipientId to check
     */
    modifier recipientExists(bytes32 id) {
        require(recipients[id].exists, "Recipient Must exist");
        _;
    }

    /**
     * @dev Guarrentees that recipient does not Exists
     * @param id receipientId to check
     */
    modifier recipientDoesNotExists(bytes32 id) {
        require(!recipients[id].exists, "Recipient Must not exists");
        _;
    }

    /**
     * @dev Guarrentees that msg.sender is wetrust owned signer address
     */
    modifier onlyByWeTrustSigner() {
        require(msg.sender == wetrustSigner, "sender must be from WeTrust Signer Address");
        _;
    }

    /**
     * @dev Guarrentees that msg.sender is wetrust owned manager address
     */
    modifier onlyByWeTrustManager() {
        require(msg.sender == wetrustManager, "sender must be from WeTrust Manager Address");
        _;
    }

    /**
     * @dev Guarrentees that msg.sender is either wetrust recipient
     * @param id receipientId to check
     */
    modifier onlyByWeTrustOrRecipient(bytes32 id) {
        require(msg.sender == wetrustSigner || msg.sender == recipients[id].owner, "sender must be from WeTrust or Recipient's owner address");
        _;
    }

    /**
     * @dev Guarrentees that contract is not in paused state
     */
    modifier onlyWhenNotPaused() {
        require(!paused, "contract is currently in paused state");
        _;
    }

    //////////////////////////////
    // Storage Variables
    /////////////////////////////

    /**
     * @dev wetrust controlled address that is used to create new NFTs
     */
    address public wetrustSigner;

    /**
     *@dev wetrust controlled address that is used to switch the signer address
     */
    address public wetrustManager;

    /**
     * @dev if paused is true, suspend most of contract's functionality
     */
    bool public paused;

    /**
     * @dev mapping of recipients from WeTrust Spring platform
     */
    mapping(bytes32 => Recipient) public recipients;
    /**
     * @dev mapping to a list of updates made by recipients
     */
    mapping(bytes32 => Update[]) public recipientUpdates;

    /**
     * @dev Stores the Artist signed Message who created the NFT
     */
    mapping (uint256 => bytes) public nftArtistSignature;

    struct Update {
        bytes32 id;
        uint256 createdAt;
    }

    struct Recipient {
        string name;
        string url;
        address owner;
        uint256 nftCount;
        bool exists;
    }

    //////////////////////////////
    // Public functions
    /////////////////////////////

    /**
     * @dev contract constructor
     */
    constructor (address signer, address manager) NFToken() public {
        wetrustSigner = signer;
        wetrustManager = manager;
    }

    /**
     * @dev Create a new NFT
     * @param tokenId create new NFT with this tokenId
     * @param receiver the owner of the new NFT
     * @param recipientId The issuer of the NFT
     * @param traits NFT Traits
     * @param nftType Type of the NFT
     */

    function createNFT(
        uint256 tokenId,
        address receiver,
        bytes32 recipientId,
        bytes32 traits,
        bytes4 nftType)
        noOwnerExists(tokenId)
        onlyByWeTrustSigner
        onlyWhenNotPaused public
    {
        mint(tokenId, receiver, recipientId, traits, nftType);
    }

    /**
     * @dev Allows anyone to redeem a token by providing a signed Message from Spring platform
     * @param signedMessage A signed Message containing the NFT parameter from Spring platform
     * The Signed Message must be concatenated in the following format
     * - address to (the smart contract address)
     * - uint256 tokenId
     * - bytes4 nftType
     * - bytes32 traits
     * - bytes32 recipientId
     * - bytes32 r of Signature
     * - bytes32 s of Signature
     * - uint8 v of Signature
     */
    function redeemToken(bytes signedMessage) onlyWhenNotPaused public {
        address to;
        uint256 tokenId;
        bytes4 nftType;
        bytes32 traits;
        bytes32 recipientId;
        bytes32 r;
        bytes32 s;
        byte vInByte;
        uint8 v;
        string memory prefix = "\x19Ethereum Signed Message:\n32";

        assembly {
            to := mload(add(signedMessage, 32))
            tokenId := mload(add(signedMessage, 64))
            nftType := mload(add(signedMessage, 96)) // first 32 bytes are data padding
            traits := mload(add(signedMessage, 100))
            recipientId := mload(add(signedMessage, 132))
            r := mload(add(signedMessage, 164))
            s := mload(add(signedMessage, 196))
            vInByte := mload(add(signedMessage, 228))
        }
        require(to == address(this), "This signed Message is not meant for this smart contract");
        v = uint8(vInByte);
        if (v < 27) {
            v += 27;
        }

        require(nft[tokenId].owner == address(0), "This token has been redeemed already");
        bytes32 msgHash = createRedeemMessageHash(tokenId, nftType, traits, recipientId);
        bytes32 preFixedMsgHash = keccak256(
            abi.encodePacked(
                prefix,
                msgHash
            ));

        address signer = ecrecover(preFixedMsgHash, v, r, s);

        require(signer == wetrustSigner, "WeTrust did not authorized this redeem script");
        return mint(tokenId, msg.sender, recipientId, traits, nftType);
    }

    /**
     * @dev Add a new reciepient of WeTrust Spring
     * @param recipientId Unique identifier of receipient
     * @param name of the Recipient
     * @param url link to the recipient's website
     * @param owner Address owned by the recipient
     */
    function addRecipient(bytes32 recipientId, string name, string url, address owner)
        onlyByWeTrustSigner
        onlyWhenNotPaused
        recipientDoesNotExists(recipientId)
        public
    {
        require(bytes(name).length > 0, "name must not be empty string"); // no empty string

        recipients[recipientId].name = name;
        recipients[recipientId].url = url;
        recipients[recipientId].owner = owner;
        recipients[recipientId].exists = true;
    }

    /**
     * @dev Add an link to the update the recipient had made
     * @param recipientId The issuer of the update
     * @param updateId unique id of the update
     */
    function addRecipientUpdate(bytes32 recipientId, bytes32 updateId)
        onlyWhenNotPaused
        recipientExists(recipientId)
        onlyByWeTrustOrRecipient(recipientId)
        public
    {
        recipientUpdates[recipientId].push(Update(updateId, now));
        emit RecipientUpdate(recipientId, updateId);
    }

    /**
     * @dev Change recipient information
     * @param recipientId to change
     * @param name new name of the recipient
     * @param url new link of the recipient
     * @param owner new address owned by the recipient
     */
    function updateRecipientInfo(bytes32 recipientId, string name, string url, address owner)
        onlyByWeTrustSigner
        onlyWhenNotPaused
        recipientExists(recipientId)
        public
    {
        require(bytes(name).length > 0, "name must not be empty string"); // no empty string

        recipients[recipientId].name = name;
        recipients[recipientId].url = url;
        recipients[recipientId].owner = owner;
    }

    /**
     * @dev add a artist signed message for a particular NFT
     * @param nftId NFT to add the signature to
     * @param artistSignature Artist Signed Message
     */
    function addArtistSignature(uint256 nftId, bytes artistSignature) onlyByWeTrustSigner onlyWhenNotPaused public {
        require(nftArtistSignature[nftId].length == 0, "Artist Signature already exist for this token"); // make sure no prior signature exists

        nftArtistSignature[nftId] = artistSignature;
    }

    /**
     * @dev Set whether or not the contract is paused
     * @param _paused status to put the contract in
     */
    function setPaused(bool _paused) onlyByWeTrustManager public {
        paused = _paused;
    }

    /**
     * @dev Transfer the WeTrust signer of NFT contract to a new address
     * @param newAddress new WeTrust owned address
     */
    function changeWeTrustSigner(address newAddress) onlyWhenNotPaused onlyByWeTrustManager public {
        wetrustSigner = newAddress;
    }

    /**
     * @dev Returns the number of updates recipients had made
     * @param recipientId receipientId to check
     */
    function getUpdateCount(bytes32 recipientId) view public returns(uint256 count) {
        return recipientUpdates[recipientId].length;
    }

    /**
     * @dev returns the message hash to be signed for redeem token
     * @param tokenId id of the token to be created
     * @param nftType Type of NFT to be created
     * @param traits Traits of NFT to be created
     * @param recipientId Issuer of the NFT
     */
    function createRedeemMessageHash(
        uint256 tokenId,
        bytes4 nftType,
        bytes32 traits,
        bytes32 recipientId)
        view public returns(bytes32 msgHash)
    {
        return keccak256(
            abi.encodePacked(
                address(this),
                tokenId,
                nftType,
                traits,
                recipientId
            ));
    }

    /**
     * @dev Determines the edition of the NFT
     *      formula used to determine edition Size given the edition Number:
     *      f(x) = min(300x + 100, 5000)
     * using equation: g(x) = 150x^2 - 50x + 1 if x <= 16
     * else g(x) = 5000(x-16) - g(16)
     * maxEdition = 5000
     * @param nextNFTcount to determine edition for
     */
    function determineEdition(uint256 nextNFTcount) pure public returns (uint16 edition) {
        uint256 output;
        uint256 valueWhenXisSixteen = 37601; // g(16)
        if (nextNFTcount < valueWhenXisSixteen) {
            output = (sqrt(2500 + (600 * (nextNFTcount - 1))) + 50) / 300;
        } else {
            output = ((nextNFTcount - valueWhenXisSixteen) / 5000) + 16;
        }

        if (output > 5000) {
            output = 5000;
        }

        edition = uint16(output); // we don't have to worry about casting because output will always be less than or equal to 5000
    }

    /**
     * @dev set new host name for this nft contract
     * @param newHostName new host name to use
     */
    function setNFTContractInfo(string newHostName, string newName, string newSymbol) onlyByWeTrustManager external {
        hostname = newHostName;
        nftName = newName;
        nftSymbol = newSymbol;
    }
    //////////////////////////
    // Private Functions
    /////////////////////////

    /**
     * @dev Find the Square root of a number
     * @param x input
     * Credit goes to: https://ethereum.stackexchange.com/questions/2910/can-i-square-root-in-solidity
     */

    function sqrt(uint x) pure internal returns (uint y) {
        uint z = (x + 1) / 2;
        y = x;
        while (z < y) {
            y = z;
            z = (x / z + z) / 2;
        }
    }

    /**
     * @dev Add the new NFT to the storage
     * @param receiver the owner of the new NFT
     * @param recipientId The issuer of the NFT
     * @param traits NFT Traits
     * @param nftType Type of the NFT
     */
    function mint(uint256 tokenId, address receiver, bytes32 recipientId, bytes32 traits, bytes4 nftType)
        recipientExists(recipientId)
        internal
    {
        nft[tokenId].owner = receiver;
        nft[tokenId].traits = traits;
        nft[tokenId].recipientId = recipientId;
        nft[tokenId].nftType = nftType;
        nft[tokenId].createdAt = now;
        nft[tokenId].edition = determineEdition(recipients[recipientId].nftCount + 1);

        recipients[recipientId].nftCount++;
        ownerToTokenList[receiver].push(tokenId);

        nftList.push(tokenId);

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

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[{"name":"_interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"recipientId","type":"bytes32"},{"name":"name","type":"string"},{"name":"url","type":"string"},{"name":"owner","type":"address"}],"name":"updateRecipientInfo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"nftArtistSignature","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"_name","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_approved","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"wetrustSigner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"uint256"}],"name":"recipientUpdates","outputs":[{"name":"id","type":"bytes32"},{"name":"createdAt","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newHostName","type":"string"},{"name":"newName","type":"string"},{"name":"newSymbol","type":"string"}],"name":"setNFTContractInfo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newAddress","type":"address"}],"name":"changeWeTrustSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"nftId","type":"uint256"},{"name":"artistSignature","type":"bytes"}],"name":"addArtistSignature","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"name":"_owner","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"hostname","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"nextNFTcount","type":"uint256"}],"name":"determineEdition","outputs":[{"name":"edition","type":"uint16"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"getOwnedTokenList","outputs":[{"name":"tokenList","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"recipientId","type":"bytes32"},{"name":"updateId","type":"bytes32"}],"name":"addRecipientUpdate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"tokenId","type":"uint256"},{"name":"receiver","type":"address"},{"name":"recipientId","type":"bytes32"},{"name":"traits","type":"bytes32"},{"name":"nftType","type":"bytes4"}],"name":"createNFT","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"recipientId","type":"bytes32"},{"name":"name","type":"string"},{"name":"url","type":"string"},{"name":"owner","type":"address"}],"name":"addRecipient","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"tokenId","type":"uint256"},{"name":"nftType","type":"bytes4"},{"name":"traits","type":"bytes32"},{"name":"recipientId","type":"bytes32"}],"name":"createRedeemMessageHash","outputs":[{"name":"msgHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"_symbol","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"nft","outputs":[{"name":"owner","type":"address"},{"name":"approval","type":"address"},{"name":"traits","type":"bytes32"},{"name":"edition","type":"uint16"},{"name":"nftType","type":"bytes4"},{"name":"recipientId","type":"bytes32"},{"name":"createdAt","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_operator","type":"address"},{"name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"wetrustManager","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"recipientId","type":"bytes32"}],"name":"getUpdateCount","outputs":[{"name":"count","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"recipients","outputs":[{"name":"name","type":"string"},{"name":"url","type":"string"},{"name":"owner","type":"address"},{"name":"nftCount","type":"uint256"},{"name":"exists","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"signedMessage","type":"bytes"}],"name":"redeemToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"signer","type":"address"},{"name":"manager","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"recipientId","type":"bytes32"},{"indexed":false,"name":"updateId","type":"bytes32"}],"name":"RecipientUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":true,"name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_approved","type":"address"},{"indexed":true,"name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_operator","type":"address"},{"indexed":false,"name":"_approved","type":"bool"}],"name":"ApprovalForAll","type":"event"}]

60806040526040805190810160405280600d81526020017f57655472757374204e6966747900000000000000000000000000000000000000815250600190805190602001906200005192919062000367565b506040805190810160405280600481526020017f5350524e00000000000000000000000000000000000000000000000000000000815250600290805190602001906200009f92919062000367565b506040805190810160405280602081526020017f68747470733a2f2f737072696e672e776574727573742e696f2f73686962612f81525060039080519060200190620000ed92919062000367565b50348015620000fb57600080fd5b5060405160408062005fcd833981018060405281019080805190602001909291908051906020019092919050505060016000806301ffc9a77c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff021916908315150217905550600160008063780e9d637c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600080635b5e139f7c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555060016000806380ac58cd7c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505062000416565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003aa57805160ff1916838001178555620003db565b82800160010185558215620003db579182015b82811115620003da578251825591602001919060010190620003bd565b5b509050620003ea9190620003ee565b5090565b6200041391905b808211156200040f576000816000905550600101620003f5565b5090565b90565b615ba780620004266000396000f3006080604052600436106101cd576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301ffc9a7146101d2578063024cc06d1461023657806302b43e8f1461031357806306fdde03146103b9578063081812fc14610449578063095ea7b3146104b65780631000d2781461050357806313b4d1861461055a57806316c38b3c146105b857806316d41a5a146105e757806318160ddd1461065257806323b872dd1461067d5780632f745c59146106ea57806342842e0e1461074b5780634f6ccce7146107b8578063503e9d33146107f95780635c975abb1461083c57806360d2bee91461086b5780636352211e146108de5780636f4a5a351461094b57806370a08231146109db5780637cae6cb514610a325780637ff70a8914610a7b5780638b3294e514610b135780638c0b158814610b525780638d4d801c14610be457806394fdbbb214610cc157806395d89b4114610d4f5780639d0214cb14610ddf578063a22cb46514610ef8578063b88d4fde14610f47578063c87b56dd14610fcc578063d3f4e3e914611072578063e48341db146110c9578063e5ef8abb1461110e578063e985e9c514611269578063ea9ce8fd146112e4575b600080fd5b3480156101de57600080fd5b5061021c60048036038101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061134d565b604051808215151515815260200191505060405180910390f35b34801561024257600080fd5b506103116004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506113b4565b005b34801561031f57600080fd5b5061033e6004803603810190808035906020019092919050505061172e565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561037e578082015181840152602081019050610363565b50505050905090810190601f1680156103ab5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103c557600080fd5b506103ce6117de565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561040e5780820151818401526020810190506103f3565b50505050905090810190601f16801561043b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561045557600080fd5b5061047460048036038101908080359060200190929190505050611880565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156104c257600080fd5b50610501600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061199d565b005b34801561050f57600080fd5b50610518611dcc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561056657600080fd5b50610593600480360381019080803560001916906020019092919080359060200190929190505050611df2565b6040518083600019166000191681526020018281526020019250505060405180910390f35b3480156105c457600080fd5b506105e5600480360381019080803515159060200190929190505050611e32565b005b3480156105f357600080fd5b50610650600480360381019080803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390505050611f3a565b005b34801561065e57600080fd5b50610667612063565b6040518082815260200191505060405180910390f35b34801561068957600080fd5b506106e8600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612070565b005b3480156106f657600080fd5b50610735600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506124de565b6040518082815260200191505060405180910390f35b34801561075757600080fd5b506107b6600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506125be565b005b3480156107c457600080fd5b506107e3600480360381019080803590602001909291905050506125df565b6040518082815260200191505060405180910390f35b34801561080557600080fd5b5061083a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061267e565b005b34801561084857600080fd5b50610851612858565b604051808215151515815260200191505060405180910390f35b34801561087757600080fd5b506108dc60048036038101908080359060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061286b565b005b3480156108ea57600080fd5b5061090960048036038101908080359060200190929190505050612af2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561095757600080fd5b50610960612c0f565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156109a0578082015181840152602081019050610985565b50505050905090810190601f1680156109cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156109e757600080fd5b50610a1c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612cad565b6040518082815260200191505060405180910390f35b348015610a3e57600080fd5b50610a5d60048036038101908080359060200190929190505050612da0565b604051808261ffff1661ffff16815260200191505060405180910390f35b348015610a8757600080fd5b50610abc600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612e0d565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610aff578082015181840152602081019050610ae4565b505050509050019250505060405180910390f35b348015610b1f57600080fd5b50610b5060048036038101908080356000191690602001909291908035600019169060200190929190505050612ea4565b005b348015610b5e57600080fd5b50610be260048036038101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035600019169060200190929190803560001916906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050613216565b005b348015610bf057600080fd5b50610cbf6004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134c2565b005b348015610ccd57600080fd5b50610d316004803603810190808035906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080356000191690602001909291908035600019169060200190929190505050613874565b60405180826000191660001916815260200191505060405180910390f35b348015610d5b57600080fd5b50610d646139ab565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610da4578082015181840152602081019050610d89565b50505050905090810190601f168015610dd15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610deb57600080fd5b50610e0a60048036038101908080359060200190929190505050613a4d565b604051808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186600019166000191681526020018561ffff1661ffff168152602001847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001836000191660001916815260200182815260200197505050505050505060405180910390f35b348015610f0457600080fd5b50610f45600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050613b06565b005b348015610f5357600080fd5b50610fca600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001919091929391929390505050613cae565b005b348015610fd857600080fd5b50610ff760048036038101908080359060200190929190505050613cf3565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561103757808201518184015260208101905061101c565b50505050905090810190601f1680156110645780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561107e57600080fd5b50611087613da0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156110d557600080fd5b506110f86004803603810190808035600019169060200190929190505050613dc6565b6040518082815260200191505060405180910390f35b34801561111a57600080fd5b5061113d6004803603810190808035600019169060200190929190505050613dee565b6040518080602001806020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200185815260200184151515158152602001838103835288818151815260200191508051906020019080838360005b838110156111c35780820151818401526020810190506111a8565b50505050905090810190601f1680156111f05780820380516001836020036101000a031916815260200191505b50838103825287818151815260200191508051906020019080838360005b8381101561122957808201518184015260208101905061120e565b50505050905090810190601f1680156112565780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390f35b34801561127557600080fd5b506112ca600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613f81565b604051808215151515815260200191505060405180910390f35b3480156112f057600080fd5b5061134b600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050614163565b005b6000806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561149f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f73656e646572206d7573742062652066726f6d2057655472757374205369676e81526020017f657220416464726573730000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600960149054906101000a900460ff1615151561154a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b83600a6000826000191660001916815260200190815260200160002060040160009054906101000a900460ff1615156115eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f526563697069656e74204d75737420657869737400000000000000000000000081525060200191505060405180910390fd5b60008451111515611664576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f6e616d65206d757374206e6f7420626520656d70747920737472696e6700000081525060200191505060405180910390fd5b83600a6000876000191660001916815260200190815260200160002060000190805190602001906116969291906159aa565b5082600a6000876000191660001916815260200190815260200160002060010190805190602001906116c99291906159aa565b5081600a6000876000191660001916815260200190815260200160002060020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b600c6020528060005260406000206000915090508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117d65780601f106117ab576101008083540402835291602001916117d6565b820191906000526020600020905b8154815290600101906020018083116117b957829003601f168201915b505050505081565b606060018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156118765780601f1061184b57610100808354040283529160200191611876565b820191906000526020600020905b81548152906001019060200180831161185957829003601f168201915b5050505050905090565b600081600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561195e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4f776e6572206d75737420657869737420666f72207468697320746f6b656e0081525060200191505060405180910390fd5b6004600084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b60008160006004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480611a9b5750600760008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b1515611b35576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260328152602001807f53656e646572206973206e6f7420616e20617574686f72697a6564206f70657281526020017f61746f72206f66207468697320746f6b656e000000000000000000000000000081525060400191505060405180910390fd5b83600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151515611c11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4f776e6572206d75737420657869737420666f72207468697320746f6b656e0081525060200191505060405180910390fd5b6004600086815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614151515611d14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d8152602001807f617070726f76656420616464726573732063616e6e6f74206265206f776e657281526020017f206f662074686520746f6b656e0000000000000000000000000000000000000081525060400191505060405180910390fd5b856004600087815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050505050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600b60205281600052604060002081815481101515611e0d57fe5b9060005260206000209060020201600091509150508060000154908060010154905082565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611f1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001807f73656e646572206d7573742062652066726f6d2057655472757374204d616e6181526020017f676572204164647265737300000000000000000000000000000000000000000081525060400191505060405180910390fd5b80600960146101000a81548160ff02191690831515021790555050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612025576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001807f73656e646572206d7573742062652066726f6d2057655472757374204d616e6181526020017f676572204164647265737300000000000000000000000000000000000000000081525060400191505060405180910390fd5b858560039190612036929190615a2a565b50838360019190612048929190615a2a565b5081816002919061205a929190615a2a565b50505050505050565b6000600580549050905090565b600082600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515612118576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f41646472657373206d757374206265206e6f6e207a65726f206164647265737381525060200191505060405180910390fd5b8260006004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806121c157503373ffffffffffffffffffffffffffffffffffffffff166121a983611880565b73ffffffffffffffffffffffffffffffffffffffff16145b806122525750600760008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b15156122ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001807f53656e64657220646f6573206e6f742068617665207065726d697373696f6e2081526020017f746f207472616e73666572207468697320546f6b656e0000000000000000000081525060400191505060405180910390fd5b84600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515156123c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4f776e6572206d75737420657869737420666f72207468697320746f6b656e0081525060200191505060405180910390fd5b6004600087815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1694508773ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415156124ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f66726f6d2061646472657373206d757374206265206f776e6572206f6620746f81526020017f6b656e496400000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6124d4878761470f565b5050505050505050565b60006124e983612cad565b8210151561255f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f696e646578206f7574206f662072616e6765000000000000000000000000000081525060200191505060405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156125ab57fe5b9060005260206000200154905092915050565b6125da83838360206040519081016040528060008152506147c7565b505050565b60006005805490508210151561265d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f696e646578206f7574206f662072616e6765000000000000000000000000000081525060200191505060405180910390fd5b60058281548110151561266c57fe5b90600052602060002001549050919050565b600960149054906101000a900460ff16151515612729576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612814576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001807f73656e646572206d7573742062652066726f6d2057655472757374204d616e6181526020017f676572204164647265737300000000000000000000000000000000000000000081525060400191505060405180910390fd5b80600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600960149054906101000a900460ff1681565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f73656e646572206d7573742062652066726f6d2057655472757374205369676e81526020017f657220416464726573730000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600960149054906101000a900460ff16151515612a01576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6000600c6000848152602001908152602001600020805460018160011615610100020316600290049050141515612ac6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d8152602001807f417274697374205369676e617475726520616c7265616479206578697374206681526020017f6f72207468697320746f6b656e0000000000000000000000000000000000000081525060400191505060405180910390fd5b80600c60008481526020019081526020016000209080519060200190612aed929190615aaa565b505050565b600081600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151515612bd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4f776e6572206d75737420657869737420666f72207468697320746f6b656e0081525060200191505060405180910390fd5b6004600084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b60038054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015612ca55780601f10612c7a57610100808354040283529160200191612ca5565b820191906000526020600020905b815481529060010190602001808311612c8857829003601f168201915b505050505081565b600081600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515612d55576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f41646472657373206d757374206265206e6f6e207a65726f206164647265737381525060200191505060405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050915050919050565b60008060006192e1905080841015612ddd5761012c6032612dcb60018703610258026109c401614edc565b01811515612dd557fe5b049150612df3565b6010611388828603811515612dee57fe5b040191505b611388821115612e035761138891505b8192505050919050565b6060600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015612e9857602002820191906000526020600020905b815481526020019060010190808311612e84575b50505050509050919050565b600960149054906101000a900460ff16151515612f4f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b81600a6000826000191660001916815260200190815260200160002060040160009054906101000a900460ff161515612ff0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f526563697069656e74204d75737420657869737400000000000000000000000081525060200191505060405180910390fd5b82600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806130b65750600a6000826000191660001916815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b1515613150576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260388152602001807f73656e646572206d7573742062652066726f6d2057655472757374206f72205281526020017f6563697069656e742773206f776e65722061646472657373000000000000000081525060400191505060405180910390fd5b600b600085600019166000191681526020019081526020016000206040805190810160405280856000191681526020014281525090806001815401808255809150509060018203906000526020600020906002020160009091929091909150600082015181600001906000191690556020820151816001015550505083600019167f724ec1338c53d3f1f20f15b3bd0abd74ff600129ff940cb5a1b71f25edd716628460405180826000191660001916815260200191505060405180910390a250505050565b84600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515613317576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001807f4f776e6572206d757374206e6f7420657869737420666f72207468697320746f81526020017f6b656e000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515613402576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f73656e646572206d7573742062652066726f6d2057655472757374205369676e81526020017f657220416464726573730000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600960149054906101000a900460ff161515156134ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6134ba8686868686614f27565b505050505050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156135ad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f73656e646572206d7573742062652066726f6d2057655472757374205369676e81526020017f657220416464726573730000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600960149054906101000a900460ff16151515613658576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b83600a6000826000191660001916815260200190815260200160002060040160009054906101000a900460ff161515156136fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f526563697069656e74204d757374206e6f74206578697374730000000000000081525060200191505060405180910390fd5b60008451111515613773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f6e616d65206d757374206e6f7420626520656d70747920737472696e6700000081525060200191505060405180910390fd5b83600a6000876000191660001916815260200190815260200160002060000190805190602001906137a59291906159aa565b5082600a6000876000191660001916815260200190815260200160002060010190805190602001906137d89291906159aa565b5081600a6000876000191660001916815260200190815260200160002060020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600a6000876000191660001916815260200190815260200160002060040160006101000a81548160ff0219169083151502179055505050505050565b60003085858585604051602001808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c01000000000000000000000000028152601401858152602001847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260040183600019166000191681526020018260001916600019168152602001955050505050506040516020818303038152906040526040518082805190602001908083835b602083101515613974578051825260208201915060208101905060208303925061394f565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209050949350505050565b606060028054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613a435780601f10613a1857610100808354040283529160200191613a43565b820191906000526020600020905b815481529060010190602001808311613a2657829003601f168201915b5050505050905090565b60046020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154908060030160009054906101000a900461ffff16908060030160029054906101000a90047c010000000000000000000000000000000000000000000000000000000002908060040154908060050154905087565b81600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515613bac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f41646472657373206d757374206265206e6f6e207a65726f206164647265737381525060200191505060405180910390fd5b81600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3184604051808215151515815260200191505060405180910390a3505050565b613cec85858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506147c7565b5050505050565b6060613d9960038054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613d8e5780601f10613d6357610100808354040283529160200191613d8e565b820191906000526020600020905b815481529060010190602001808311613d7157829003601f168201915b505050505083615246565b9050919050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600b60008360001916600019168152602001908152602001600020805490509050919050565b600a602052806000526040600020600091509050806000018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613e9a5780601f10613e6f57610100808354040283529160200191613e9a565b820191906000526020600020905b815481529060010190602001808311613e7d57829003601f168201915b505050505090806001018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613f385780601f10613f0d57610100808354040283529160200191613f38565b820191906000526020600020905b815481529060010190602001808311613f1b57829003601f168201915b5050505050908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030154908060040160009054906101000a900460ff16905085565b600082600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515614029576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f41646472657373206d757374206265206e6f6e207a65726f206164647265737381525060200191505060405180910390fd5b82600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515156140cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f41646472657373206d757374206265206e6f6e207a65726f206164647265737381525060200191505060405180910390fd5b600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169250505092915050565b600080600080600080600080600060606000806000600960149054906101000a900460ff16151515614223576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6040805190810160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250935060208e01519c5060408e01519b5060608e01519a5060648e0151995060848e0151985060a48e0151975060c48e0151965060e48e015195503073ffffffffffffffffffffffffffffffffffffffff168d73ffffffffffffffffffffffffffffffffffffffff1614151561435c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260388152602001807f54686973207369676e6564204d657373616765206973206e6f74206d65616e7481526020017f20666f72207468697320736d61727420636f6e7472616374000000000000000081525060400191505060405180910390fd5b857f010000000000000000000000000000000000000000000000000000000000000090049450601b8560ff16101561439557601b850194505b600073ffffffffffffffffffffffffffffffffffffffff16600460008e815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515614495576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f5468697320746f6b656e20686173206265656e2072656465656d656420616c7281526020017f656164790000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6144a18c8c8c8c613874565b925083836040516020018083805190602001908083835b6020831015156144dd57805182526020820191506020810190506020830392506144b8565b6001836020036101000a0380198251168184511680821785525050505050509050018260001916600019168152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831015156145555780518252602082019150602081019050602083039250614530565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150600182868a8a604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af11580156145fb573d6000803e3d6000fd5b505050602060405103519050600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415156146f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d8152602001807f5765547275737420646964206e6f7420617574686f72697a656420746869732081526020017f72656465656d207363726970740000000000000000000000000000000000000081525060400191505060405180910390fd5b6146ff8c338b8d8f614f27565b5050505050505050505050505050565b60006004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050614753826154e1565b61475d818361558a565b61476783836157d3565b818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60008084600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515614870576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f41646472657373206d757374206265206e6f6e207a65726f206164647265737381525060200191505060405180910390fd5b8460006004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061491957503373ffffffffffffffffffffffffffffffffffffffff1661490183611880565b73ffffffffffffffffffffffffffffffffffffffff16145b806149aa5750600760008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b1515614a44576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001807f53656e64657220646f6573206e6f742068617665207065726d697373696f6e2081526020017f746f207472616e73666572207468697320546f6b656e0000000000000000000081525060400191505060405180910390fd5b86600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151515614b20576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4f776e6572206d75737420657869737420666f72207468697320746f6b656e0081525060200191505060405180910390fd5b6004600089815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508973ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16141515614c22576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f66726f6d2061646472657373206d757374206265206f776e6572206f6620746f81526020017f6b656e496400000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b614c2c898961470f565b614c4b8973ffffffffffffffffffffffffffffffffffffffff16615997565b15614ed0578873ffffffffffffffffffffffffffffffffffffffff1663150b7a02338c8b8b6040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614d45578082015181840152602081019050614d2a565b50505050905090810190601f168015614d725780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015614d9457600080fd5b505af1158015614da8573d6000803e3d6000fd5b505050506040513d6020811015614dbe57600080fd5b8101908080519060200190929190505050945063150b7a027c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141515614ecf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260398152602001807f726563696576657220636f6e747261637420646964206e6f742072657475726e81526020017f2074686520636f72726563742072657475726e2076616c75650000000000000081525060400191505060405180910390fd5b5b50505050505050505050565b600080600260018401811515614eee57fe5b0490508291505b81811015614f21578091506002818285811515614f0e57fe5b0401811515614f1957fe5b049050614ef5565b50919050565b82600a6000826000191660001916815260200190815260200160002060040160009054906101000a900460ff161515614fc8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f526563697069656e74204d75737420657869737400000000000000000000000081525060200191505060405180910390fd5b846004600088815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260046000888152602001908152602001600020600201816000191690555083600460008881526020019081526020016000206004018160001916905550816004600088815260200190815260200160002060030160026101000a81548163ffffffff02191690837c0100000000000000000000000000000000000000000000000000000000900402179055504260046000888152602001908152602001600020600501819055506150ef6001600a600087600019166000191681526020019081526020016000206003015401612da0565b6004600088815260200190815260200160002060030160006101000a81548161ffff021916908361ffff160217905550600a6000856000191660001916815260200190815260200160002060030160008154809291906001019190505550600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208690806001815401808255809150509060018203906000526020600020016000909192909190915055506005869080600181540180825580915050906001820390600052602060002001600090919290919091505550858573ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050505050565b606060006060600080606080600060649650866040519080825280601f01601f19166020018201604052801561528b5781602001602082028038833980820191505090505b509550600094505b60008914151561532a57600a898115156152a957fe5b069350600a898115156152b857fe5b049850836030017f01000000000000000000000000000000000000000000000000000000000000000286868060010197508151811015156152f557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350615293565b899250848351016040519080825280601f01601f1916602001820160405280156153635781602001602082028038833980820191505090505b509150600090505b825181101561541857828181518110151561538257fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f01000000000000000000000000000000000000000000000000000000000000000282828151811015156153db57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061536b565b600090505b848110156154d1578581600187030381518110151561543857fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002828451830181518110151561549457fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061541d565b8197505050505050505092915050565b600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515615587576004600082815260200190815260200160002060010160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b50565b6000808373ffffffffffffffffffffffffffffffffffffffff166004600085815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561568c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f66726f6d2061646472657373206d757374206265206f776e6572206f6620746f81526020017f6b656e496400000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209150600082805490501115156156dd57fe5b600090505b8180549050811015615794578282828154811015156156fd57fe5b906000526020600020015414156157875781600183805490500381548110151561572357fe5b9060005260206000200154828281548110151561573c57fe5b906000526020600020018190555081600183805490500381548110151561575f57fe5b9060005260206000200160009055818054809190600190036157819190615b2a565b50615794565b80806001019150506156e2565b6004600084815260200190815260200160002060000160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550505050565b80600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156158d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001807f4f776e6572206d757374206e6f7420657869737420666f72207468697320746f81526020017f6b656e000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b826004600084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020829080600181540180825580915050906001820390600052602060002001600090919290919091505550505050565b600080823b905060008111915050919050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106159eb57805160ff1916838001178555615a19565b82800160010185558215615a19579182015b82811115615a185782518255916020019190600101906159fd565b5b509050615a269190615b56565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615a6b57803560ff1916838001178555615a99565b82800160010185558215615a99579182015b82811115615a98578235825591602001919060010190615a7d565b5b509050615aa69190615b56565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615aeb57805160ff1916838001178555615b19565b82800160010185558215615b19579182015b82811115615b18578251825591602001919060010190615afd565b5b509050615b269190615b56565b5090565b815481835581811115615b5157818360005260206000209182019101615b509190615b56565b5b505050565b615b7891905b80821115615b74576000816000905550600101615b5c565b5090565b905600a165627a7a72305820514dedde700f631ebbb6f7b3851e82b40362df44bcf3bfcd0fa39e62f39ff67c002900000000000000000000000073d2548a9e19cbeb4b361ba963ad4977e413787d0000000000000000000000000ed8c3d25849fe3fe918a8863a04e71036cbc501

Deployed Bytecode

0x6080604052600436106101cd576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301ffc9a7146101d2578063024cc06d1461023657806302b43e8f1461031357806306fdde03146103b9578063081812fc14610449578063095ea7b3146104b65780631000d2781461050357806313b4d1861461055a57806316c38b3c146105b857806316d41a5a146105e757806318160ddd1461065257806323b872dd1461067d5780632f745c59146106ea57806342842e0e1461074b5780634f6ccce7146107b8578063503e9d33146107f95780635c975abb1461083c57806360d2bee91461086b5780636352211e146108de5780636f4a5a351461094b57806370a08231146109db5780637cae6cb514610a325780637ff70a8914610a7b5780638b3294e514610b135780638c0b158814610b525780638d4d801c14610be457806394fdbbb214610cc157806395d89b4114610d4f5780639d0214cb14610ddf578063a22cb46514610ef8578063b88d4fde14610f47578063c87b56dd14610fcc578063d3f4e3e914611072578063e48341db146110c9578063e5ef8abb1461110e578063e985e9c514611269578063ea9ce8fd146112e4575b600080fd5b3480156101de57600080fd5b5061021c60048036038101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061134d565b604051808215151515815260200191505060405180910390f35b34801561024257600080fd5b506103116004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506113b4565b005b34801561031f57600080fd5b5061033e6004803603810190808035906020019092919050505061172e565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561037e578082015181840152602081019050610363565b50505050905090810190601f1680156103ab5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103c557600080fd5b506103ce6117de565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561040e5780820151818401526020810190506103f3565b50505050905090810190601f16801561043b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561045557600080fd5b5061047460048036038101908080359060200190929190505050611880565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156104c257600080fd5b50610501600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061199d565b005b34801561050f57600080fd5b50610518611dcc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561056657600080fd5b50610593600480360381019080803560001916906020019092919080359060200190929190505050611df2565b6040518083600019166000191681526020018281526020019250505060405180910390f35b3480156105c457600080fd5b506105e5600480360381019080803515159060200190929190505050611e32565b005b3480156105f357600080fd5b50610650600480360381019080803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390505050611f3a565b005b34801561065e57600080fd5b50610667612063565b6040518082815260200191505060405180910390f35b34801561068957600080fd5b506106e8600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612070565b005b3480156106f657600080fd5b50610735600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506124de565b6040518082815260200191505060405180910390f35b34801561075757600080fd5b506107b6600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506125be565b005b3480156107c457600080fd5b506107e3600480360381019080803590602001909291905050506125df565b6040518082815260200191505060405180910390f35b34801561080557600080fd5b5061083a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061267e565b005b34801561084857600080fd5b50610851612858565b604051808215151515815260200191505060405180910390f35b34801561087757600080fd5b506108dc60048036038101908080359060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061286b565b005b3480156108ea57600080fd5b5061090960048036038101908080359060200190929190505050612af2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561095757600080fd5b50610960612c0f565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156109a0578082015181840152602081019050610985565b50505050905090810190601f1680156109cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156109e757600080fd5b50610a1c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612cad565b6040518082815260200191505060405180910390f35b348015610a3e57600080fd5b50610a5d60048036038101908080359060200190929190505050612da0565b604051808261ffff1661ffff16815260200191505060405180910390f35b348015610a8757600080fd5b50610abc600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612e0d565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610aff578082015181840152602081019050610ae4565b505050509050019250505060405180910390f35b348015610b1f57600080fd5b50610b5060048036038101908080356000191690602001909291908035600019169060200190929190505050612ea4565b005b348015610b5e57600080fd5b50610be260048036038101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035600019169060200190929190803560001916906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050613216565b005b348015610bf057600080fd5b50610cbf6004803603810190808035600019169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134c2565b005b348015610ccd57600080fd5b50610d316004803603810190808035906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080356000191690602001909291908035600019169060200190929190505050613874565b60405180826000191660001916815260200191505060405180910390f35b348015610d5b57600080fd5b50610d646139ab565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610da4578082015181840152602081019050610d89565b50505050905090810190601f168015610dd15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610deb57600080fd5b50610e0a60048036038101908080359060200190929190505050613a4d565b604051808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186600019166000191681526020018561ffff1661ffff168152602001847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001836000191660001916815260200182815260200197505050505050505060405180910390f35b348015610f0457600080fd5b50610f45600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050613b06565b005b348015610f5357600080fd5b50610fca600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001919091929391929390505050613cae565b005b348015610fd857600080fd5b50610ff760048036038101908080359060200190929190505050613cf3565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561103757808201518184015260208101905061101c565b50505050905090810190601f1680156110645780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561107e57600080fd5b50611087613da0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156110d557600080fd5b506110f86004803603810190808035600019169060200190929190505050613dc6565b6040518082815260200191505060405180910390f35b34801561111a57600080fd5b5061113d6004803603810190808035600019169060200190929190505050613dee565b6040518080602001806020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200185815260200184151515158152602001838103835288818151815260200191508051906020019080838360005b838110156111c35780820151818401526020810190506111a8565b50505050905090810190601f1680156111f05780820380516001836020036101000a031916815260200191505b50838103825287818151815260200191508051906020019080838360005b8381101561122957808201518184015260208101905061120e565b50505050905090810190601f1680156112565780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390f35b34801561127557600080fd5b506112ca600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613f81565b604051808215151515815260200191505060405180910390f35b3480156112f057600080fd5b5061134b600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050614163565b005b6000806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561149f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f73656e646572206d7573742062652066726f6d2057655472757374205369676e81526020017f657220416464726573730000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600960149054906101000a900460ff1615151561154a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b83600a6000826000191660001916815260200190815260200160002060040160009054906101000a900460ff1615156115eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f526563697069656e74204d75737420657869737400000000000000000000000081525060200191505060405180910390fd5b60008451111515611664576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f6e616d65206d757374206e6f7420626520656d70747920737472696e6700000081525060200191505060405180910390fd5b83600a6000876000191660001916815260200190815260200160002060000190805190602001906116969291906159aa565b5082600a6000876000191660001916815260200190815260200160002060010190805190602001906116c99291906159aa565b5081600a6000876000191660001916815260200190815260200160002060020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b600c6020528060005260406000206000915090508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117d65780601f106117ab576101008083540402835291602001916117d6565b820191906000526020600020905b8154815290600101906020018083116117b957829003601f168201915b505050505081565b606060018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156118765780601f1061184b57610100808354040283529160200191611876565b820191906000526020600020905b81548152906001019060200180831161185957829003601f168201915b5050505050905090565b600081600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561195e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4f776e6572206d75737420657869737420666f72207468697320746f6b656e0081525060200191505060405180910390fd5b6004600084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b60008160006004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480611a9b5750600760008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b1515611b35576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260328152602001807f53656e646572206973206e6f7420616e20617574686f72697a6564206f70657281526020017f61746f72206f66207468697320746f6b656e000000000000000000000000000081525060400191505060405180910390fd5b83600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151515611c11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4f776e6572206d75737420657869737420666f72207468697320746f6b656e0081525060200191505060405180910390fd5b6004600086815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614151515611d14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d8152602001807f617070726f76656420616464726573732063616e6e6f74206265206f776e657281526020017f206f662074686520746f6b656e0000000000000000000000000000000000000081525060400191505060405180910390fd5b856004600087815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050505050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600b60205281600052604060002081815481101515611e0d57fe5b9060005260206000209060020201600091509150508060000154908060010154905082565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611f1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001807f73656e646572206d7573742062652066726f6d2057655472757374204d616e6181526020017f676572204164647265737300000000000000000000000000000000000000000081525060400191505060405180910390fd5b80600960146101000a81548160ff02191690831515021790555050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612025576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001807f73656e646572206d7573742062652066726f6d2057655472757374204d616e6181526020017f676572204164647265737300000000000000000000000000000000000000000081525060400191505060405180910390fd5b858560039190612036929190615a2a565b50838360019190612048929190615a2a565b5081816002919061205a929190615a2a565b50505050505050565b6000600580549050905090565b600082600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515612118576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f41646472657373206d757374206265206e6f6e207a65726f206164647265737381525060200191505060405180910390fd5b8260006004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806121c157503373ffffffffffffffffffffffffffffffffffffffff166121a983611880565b73ffffffffffffffffffffffffffffffffffffffff16145b806122525750600760008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b15156122ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001807f53656e64657220646f6573206e6f742068617665207065726d697373696f6e2081526020017f746f207472616e73666572207468697320546f6b656e0000000000000000000081525060400191505060405180910390fd5b84600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515156123c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4f776e6572206d75737420657869737420666f72207468697320746f6b656e0081525060200191505060405180910390fd5b6004600087815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1694508773ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415156124ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f66726f6d2061646472657373206d757374206265206f776e6572206f6620746f81526020017f6b656e496400000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6124d4878761470f565b5050505050505050565b60006124e983612cad565b8210151561255f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f696e646578206f7574206f662072616e6765000000000000000000000000000081525060200191505060405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156125ab57fe5b9060005260206000200154905092915050565b6125da83838360206040519081016040528060008152506147c7565b505050565b60006005805490508210151561265d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f696e646578206f7574206f662072616e6765000000000000000000000000000081525060200191505060405180910390fd5b60058281548110151561266c57fe5b90600052602060002001549050919050565b600960149054906101000a900460ff16151515612729576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612814576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001807f73656e646572206d7573742062652066726f6d2057655472757374204d616e6181526020017f676572204164647265737300000000000000000000000000000000000000000081525060400191505060405180910390fd5b80600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600960149054906101000a900460ff1681565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f73656e646572206d7573742062652066726f6d2057655472757374205369676e81526020017f657220416464726573730000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600960149054906101000a900460ff16151515612a01576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6000600c6000848152602001908152602001600020805460018160011615610100020316600290049050141515612ac6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d8152602001807f417274697374205369676e617475726520616c7265616479206578697374206681526020017f6f72207468697320746f6b656e0000000000000000000000000000000000000081525060400191505060405180910390fd5b80600c60008481526020019081526020016000209080519060200190612aed929190615aaa565b505050565b600081600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151515612bd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4f776e6572206d75737420657869737420666f72207468697320746f6b656e0081525060200191505060405180910390fd5b6004600084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b60038054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015612ca55780601f10612c7a57610100808354040283529160200191612ca5565b820191906000526020600020905b815481529060010190602001808311612c8857829003601f168201915b505050505081565b600081600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515612d55576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f41646472657373206d757374206265206e6f6e207a65726f206164647265737381525060200191505060405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050915050919050565b60008060006192e1905080841015612ddd5761012c6032612dcb60018703610258026109c401614edc565b01811515612dd557fe5b049150612df3565b6010611388828603811515612dee57fe5b040191505b611388821115612e035761138891505b8192505050919050565b6060600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015612e9857602002820191906000526020600020905b815481526020019060010190808311612e84575b50505050509050919050565b600960149054906101000a900460ff16151515612f4f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b81600a6000826000191660001916815260200190815260200160002060040160009054906101000a900460ff161515612ff0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f526563697069656e74204d75737420657869737400000000000000000000000081525060200191505060405180910390fd5b82600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806130b65750600a6000826000191660001916815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b1515613150576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260388152602001807f73656e646572206d7573742062652066726f6d2057655472757374206f72205281526020017f6563697069656e742773206f776e65722061646472657373000000000000000081525060400191505060405180910390fd5b600b600085600019166000191681526020019081526020016000206040805190810160405280856000191681526020014281525090806001815401808255809150509060018203906000526020600020906002020160009091929091909150600082015181600001906000191690556020820151816001015550505083600019167f724ec1338c53d3f1f20f15b3bd0abd74ff600129ff940cb5a1b71f25edd716628460405180826000191660001916815260200191505060405180910390a250505050565b84600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515613317576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001807f4f776e6572206d757374206e6f7420657869737420666f72207468697320746f81526020017f6b656e000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515613402576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f73656e646572206d7573742062652066726f6d2057655472757374205369676e81526020017f657220416464726573730000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600960149054906101000a900460ff161515156134ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6134ba8686868686614f27565b505050505050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156135ad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f73656e646572206d7573742062652066726f6d2057655472757374205369676e81526020017f657220416464726573730000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600960149054906101000a900460ff16151515613658576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b83600a6000826000191660001916815260200190815260200160002060040160009054906101000a900460ff161515156136fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f526563697069656e74204d757374206e6f74206578697374730000000000000081525060200191505060405180910390fd5b60008451111515613773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f6e616d65206d757374206e6f7420626520656d70747920737472696e6700000081525060200191505060405180910390fd5b83600a6000876000191660001916815260200190815260200160002060000190805190602001906137a59291906159aa565b5082600a6000876000191660001916815260200190815260200160002060010190805190602001906137d89291906159aa565b5081600a6000876000191660001916815260200190815260200160002060020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600a6000876000191660001916815260200190815260200160002060040160006101000a81548160ff0219169083151502179055505050505050565b60003085858585604051602001808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c01000000000000000000000000028152601401858152602001847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260040183600019166000191681526020018260001916600019168152602001955050505050506040516020818303038152906040526040518082805190602001908083835b602083101515613974578051825260208201915060208101905060208303925061394f565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209050949350505050565b606060028054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613a435780601f10613a1857610100808354040283529160200191613a43565b820191906000526020600020905b815481529060010190602001808311613a2657829003601f168201915b5050505050905090565b60046020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154908060030160009054906101000a900461ffff16908060030160029054906101000a90047c010000000000000000000000000000000000000000000000000000000002908060040154908060050154905087565b81600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515613bac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f41646472657373206d757374206265206e6f6e207a65726f206164647265737381525060200191505060405180910390fd5b81600760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3184604051808215151515815260200191505060405180910390a3505050565b613cec85858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506147c7565b5050505050565b6060613d9960038054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613d8e5780601f10613d6357610100808354040283529160200191613d8e565b820191906000526020600020905b815481529060010190602001808311613d7157829003601f168201915b505050505083615246565b9050919050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600b60008360001916600019168152602001908152602001600020805490509050919050565b600a602052806000526040600020600091509050806000018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613e9a5780601f10613e6f57610100808354040283529160200191613e9a565b820191906000526020600020905b815481529060010190602001808311613e7d57829003601f168201915b505050505090806001018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613f385780601f10613f0d57610100808354040283529160200191613f38565b820191906000526020600020905b815481529060010190602001808311613f1b57829003601f168201915b5050505050908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030154908060040160009054906101000a900460ff16905085565b600082600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515614029576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f41646472657373206d757374206265206e6f6e207a65726f206164647265737381525060200191505060405180910390fd5b82600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515156140cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f41646472657373206d757374206265206e6f6e207a65726f206164647265737381525060200191505060405180910390fd5b600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169250505092915050565b600080600080600080600080600060606000806000600960149054906101000a900460ff16151515614223576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f636f6e74726163742069732063757272656e746c7920696e207061757365642081526020017f737461746500000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6040805190810160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250935060208e01519c5060408e01519b5060608e01519a5060648e0151995060848e0151985060a48e0151975060c48e0151965060e48e015195503073ffffffffffffffffffffffffffffffffffffffff168d73ffffffffffffffffffffffffffffffffffffffff1614151561435c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260388152602001807f54686973207369676e6564204d657373616765206973206e6f74206d65616e7481526020017f20666f72207468697320736d61727420636f6e7472616374000000000000000081525060400191505060405180910390fd5b857f010000000000000000000000000000000000000000000000000000000000000090049450601b8560ff16101561439557601b850194505b600073ffffffffffffffffffffffffffffffffffffffff16600460008e815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515614495576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f5468697320746f6b656e20686173206265656e2072656465656d656420616c7281526020017f656164790000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6144a18c8c8c8c613874565b925083836040516020018083805190602001908083835b6020831015156144dd57805182526020820191506020810190506020830392506144b8565b6001836020036101000a0380198251168184511680821785525050505050509050018260001916600019168152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831015156145555780518252602082019150602081019050602083039250614530565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150600182868a8a604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af11580156145fb573d6000803e3d6000fd5b505050602060405103519050600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415156146f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d8152602001807f5765547275737420646964206e6f7420617574686f72697a656420746869732081526020017f72656465656d207363726970740000000000000000000000000000000000000081525060400191505060405180910390fd5b6146ff8c338b8d8f614f27565b5050505050505050505050505050565b60006004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050614753826154e1565b61475d818361558a565b61476783836157d3565b818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60008084600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515614870576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f41646472657373206d757374206265206e6f6e207a65726f206164647265737381525060200191505060405180910390fd5b8460006004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061491957503373ffffffffffffffffffffffffffffffffffffffff1661490183611880565b73ffffffffffffffffffffffffffffffffffffffff16145b806149aa5750600760008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b1515614a44576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001807f53656e64657220646f6573206e6f742068617665207065726d697373696f6e2081526020017f746f207472616e73666572207468697320546f6b656e0000000000000000000081525060400191505060405180910390fd5b86600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151515614b20576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4f776e6572206d75737420657869737420666f72207468697320746f6b656e0081525060200191505060405180910390fd5b6004600089815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508973ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16141515614c22576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f66726f6d2061646472657373206d757374206265206f776e6572206f6620746f81526020017f6b656e496400000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b614c2c898961470f565b614c4b8973ffffffffffffffffffffffffffffffffffffffff16615997565b15614ed0578873ffffffffffffffffffffffffffffffffffffffff1663150b7a02338c8b8b6040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614d45578082015181840152602081019050614d2a565b50505050905090810190601f168015614d725780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015614d9457600080fd5b505af1158015614da8573d6000803e3d6000fd5b505050506040513d6020811015614dbe57600080fd5b8101908080519060200190929190505050945063150b7a027c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141515614ecf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260398152602001807f726563696576657220636f6e747261637420646964206e6f742072657475726e81526020017f2074686520636f72726563742072657475726e2076616c75650000000000000081525060400191505060405180910390fd5b5b50505050505050505050565b600080600260018401811515614eee57fe5b0490508291505b81811015614f21578091506002818285811515614f0e57fe5b0401811515614f1957fe5b049050614ef5565b50919050565b82600a6000826000191660001916815260200190815260200160002060040160009054906101000a900460ff161515614fc8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f526563697069656e74204d75737420657869737400000000000000000000000081525060200191505060405180910390fd5b846004600088815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260046000888152602001908152602001600020600201816000191690555083600460008881526020019081526020016000206004018160001916905550816004600088815260200190815260200160002060030160026101000a81548163ffffffff02191690837c0100000000000000000000000000000000000000000000000000000000900402179055504260046000888152602001908152602001600020600501819055506150ef6001600a600087600019166000191681526020019081526020016000206003015401612da0565b6004600088815260200190815260200160002060030160006101000a81548161ffff021916908361ffff160217905550600a6000856000191660001916815260200190815260200160002060030160008154809291906001019190505550600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208690806001815401808255809150509060018203906000526020600020016000909192909190915055506005869080600181540180825580915050906001820390600052602060002001600090919290919091505550858573ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050505050565b606060006060600080606080600060649650866040519080825280601f01601f19166020018201604052801561528b5781602001602082028038833980820191505090505b509550600094505b60008914151561532a57600a898115156152a957fe5b069350600a898115156152b857fe5b049850836030017f01000000000000000000000000000000000000000000000000000000000000000286868060010197508151811015156152f557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350615293565b899250848351016040519080825280601f01601f1916602001820160405280156153635781602001602082028038833980820191505090505b509150600090505b825181101561541857828181518110151561538257fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f01000000000000000000000000000000000000000000000000000000000000000282828151811015156153db57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061536b565b600090505b848110156154d1578581600187030381518110151561543857fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002828451830181518110151561549457fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061541d565b8197505050505050505092915050565b600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515615587576004600082815260200190815260200160002060010160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b50565b6000808373ffffffffffffffffffffffffffffffffffffffff166004600085815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561568c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f66726f6d2061646472657373206d757374206265206f776e6572206f6620746f81526020017f6b656e496400000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209150600082805490501115156156dd57fe5b600090505b8180549050811015615794578282828154811015156156fd57fe5b906000526020600020015414156157875781600183805490500381548110151561572357fe5b9060005260206000200154828281548110151561573c57fe5b906000526020600020018190555081600183805490500381548110151561575f57fe5b9060005260206000200160009055818054809190600190036157819190615b2a565b50615794565b80806001019150506156e2565b6004600084815260200190815260200160002060000160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550505050565b80600073ffffffffffffffffffffffffffffffffffffffff166004600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156158d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001807f4f776e6572206d757374206e6f7420657869737420666f72207468697320746f81526020017f6b656e000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b826004600084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020829080600181540180825580915050906001820390600052602060002001600090919290919091505550505050565b600080823b905060008111915050919050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106159eb57805160ff1916838001178555615a19565b82800160010185558215615a19579182015b82811115615a185782518255916020019190600101906159fd565b5b509050615a269190615b56565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615a6b57803560ff1916838001178555615a99565b82800160010185558215615a99579182015b82811115615a98578235825591602001919060010190615a7d565b5b509050615aa69190615b56565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615aeb57805160ff1916838001178555615b19565b82800160010185558215615b19579182015b82811115615b18578251825591602001919060010190615afd565b5b509050615b269190615b56565b5090565b815481835581811115615b5157818360005260206000209182019101615b509190615b56565b5b505050565b615b7891905b80821115615b74576000816000905550600101615b5c565b5090565b905600a165627a7a72305820514dedde700f631ebbb6f7b3851e82b40362df44bcf3bfcd0fa39e62f39ff67c0029

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000073d2548a9e19cbeb4b361ba963ad4977e413787d0000000000000000000000000ed8c3d25849fe3fe918a8863a04e71036cbc501

-----Decoded View---------------
Arg [0] : signer (address): 0x73d2548a9e19cbEb4B361BA963AD4977e413787d
Arg [1] : manager (address): 0x0Ed8C3d25849fe3fe918A8863A04E71036cbc501

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000073d2548a9e19cbeb4b361ba963ad4977e413787d
Arg [1] : 0000000000000000000000000ed8c3d25849fe3fe918a8863a04e71036cbc501


Swarm Source

bzzr://514dedde700f631ebbb6f7b3851e82b40362df44bcf3bfcd0fa39e62f39ff67c
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.