Latest 25 transactions from a total of 69 transactions

TxHash Age From To Value [TxFee]
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d115 days 18 hrs ago0x0b3cbb67ebafbf6c9d8d17f5db1bada4b2cffc5a  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.000361019
0xdcad2ec689691189a47ce8869ac6bd4a59c6e897d9850921037c6f7d8ec43e6a116 days 12 hrs ago0xb0b0b249b7e97d1c5ce80f283425fd9f33c6e4e1  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.000370619
0xf91582ee9e900ba6d6528762d8d7398baa85b963efe3bff5bb6aa9e8063b01b2116 days 13 hrs ago0x0b3cbb67ebafbf6c9d8d17f5db1bada4b2cffc5a  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.0003971209
0x69e8371f1251490464b48fb7ca83c598bbcbc3d7eb7c7c30c1a7fac82e05b17e125 days 15 hrs ago0x0b3cbb67ebafbf6c9d8d17f5db1bada4b2cffc5a  IN   0xcbf788b40d94cba28052e870298334dca837143a0.001325893943325 Ether0.0017748867
0x67d70a28324a059be599a0e4200b6dce0763bb5f62ea7890ceb5d0e551a55a3a125 days 15 hrs ago0x3228f93390612218a7d55503a3bdd46c4fbd1fd3  IN   0xcbf788b40d94cba28052e870298334dca837143a0.001325893943325 Ether0.008700425
0xd1a012683be6d7beb610b9367c5c828d29373b29ffa0a0caf470abc5712bb9aa125 days 15 hrs ago0x3228f93390612218a7d55503a3bdd46c4fbd1fd3  IN   0xcbf788b40d94cba28052e870298334dca837143a0.001325893943325 Ether0.000696034
0xd4ba8617a3d944d26d9e71d120d0c017c0f96694b7a329dfd41764e8a69a61c1125 days 15 hrs ago0x3228f93390612218a7d55503a3bdd46c4fbd1fd3  IN   0xcbf788b40d94cba28052e870298334dca837143a0.001325893943325 Ether0.00008795
0x17bf900f2fdd4e70b7eac3aa777a1b327e5eb84afc3d526ad0fab93e6308de98125 days 17 hrs ago0x0b3cbb67ebafbf6c9d8d17f5db1bada4b2cffc5a  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.000337066
0x4165f43daa25654999498d61399a6b33c9cfd4c20db30ba1a569353ca2ca2485125 days 22 hrs ago0xf3c029952c8f294acf29a3ccfffaeabe6395ef0a  IN   0xcbf788b40d94cba28052e870298334dca837143a0.001325893943325 Ether0.00008795
0x64b3149f0e2d99bb1b12bdc4963a22ff904b3c4fe0ff2b21cb1be07d06029cef125 days 22 hrs ago0xf3c029952c8f294acf29a3ccfffaeabe6395ef0a  IN   0xcbf788b40d94cba28052e870298334dca837143a0.001325893943325 Ether0.00008795
0xe896d14ff56531ee897757b750099d39c1ad9f81bfd5d783a3ae50012a068cc1125 days 23 hrs ago0x0b3cbb67ebafbf6c9d8d17f5db1bada4b2cffc5a  IN   0xcbf788b40d94cba28052e870298334dca837143a0.001325893943325 Ether0.000696034
0x65a1231939b0c92fb0fcbdb786cb7dbc4bfa4c73d9aa4ca6d2cfae2dde2c85c2126 days 11 hrs ago0x0b3cbb67ebafbf6c9d8d17f5db1bada4b2cffc5a  IN   0xcbf788b40d94cba28052e870298334dca837143a0.001325893943325 Ether0.00008795
0xd8d55b1a22daf5737264c107e3c0ec4e2b1bbe39a564af72a6b9439b94b940b0126 days 11 hrs ago0xf3c029952c8f294acf29a3ccfffaeabe6395ef0a  IN   0xcbf788b40d94cba28052e870298334dca837143a0.001325893943325 Ether0.000696034
0xef7313ad5ea763969b9c024a85c73375fb35206c6954349cbb46557a92bde9dd126 days 11 hrs ago0x0b3cbb67ebafbf6c9d8d17f5db1bada4b2cffc5a  IN   0xcbf788b40d94cba28052e870298334dca837143a0.00403530464774 Ether0.0019664458
0x55dd3fc29870cac206d1c6900880994d9ba6f57333a736ba08617d049cee51c6126 days 12 hrs ago0x0b3cbb67ebafbf6c9d8d17f5db1bada4b2cffc5a  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.001085271
0x1aa5ced2b22f11f594cde3d48d44b9d122d02987485107c35fa12c540647d01e144 days 15 hrs ago0xb0b0b249b7e97d1c5ce80f283425fd9f33c6e4e1  IN   0xcbf788b40d94cba28052e870298334dca837143a0.007529263275738 Ether0.000367217
0x10f6364d9ab40bd7b811c99ddb9f98a2fbd586d4b71899b1670f892ea1914a50145 days 11 hrs ago0x0b3cbb67ebafbf6c9d8d17f5db1bada4b2cffc5a  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.00077345
0x9107c8c88bb36a666e2f80c00bf5c80a8f8f6418914e73ea6b542ff40bcd3972145 days 11 hrs ago0x0b3cbb67ebafbf6c9d8d17f5db1bada4b2cffc5a  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.000770702
0x2bc143eeb2b4db9c38723029f2592c4c6a6f08f3d04a478e03d6235eac0619c1145 days 14 hrs ago0x0b3cbb67ebafbf6c9d8d17f5db1bada4b2cffc5a  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.0035857
0x0f007ff2872d8de69e5cbcf8519e99ca4b34e829127b62e9ef938ce131a4fe19145 days 15 hrs ago0xb0b0b249b7e97d1c5ce80f283425fd9f33c6e4e1  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.000177528
0x1949573fe324085e60317c8adc55626d19a82bf32edab29d66af496d17d28ea2151 days 14 hrs ago0x3228f93390612218a7d55503a3bdd46c4fbd1fd3  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.000044749
0x7bf78267aacde766937c659aa502c817453d06175187a1a171cdd79cb1aa0d88153 days 13 hrs ago0xb0b0b249b7e97d1c5ce80f283425fd9f33c6e4e1  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.001048473
0x5beeb0d6833c0bf4318672d9d35b279ae0b2dd0ca27da109f154f79c8c803146153 days 14 hrs ago0x94f64d3b1a40274f8fdc647bd21d32119596eadc  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.000399994
0x111a10e09a12f1194f23d0dbc408f044fa29ac3bb9ba418a1b6d48afdd84578a153 days 14 hrs ago0x94f64d3b1a40274f8fdc647bd21d32119596eadc  IN   0xcbf788b40d94cba28052e870298334dca837143a0.015879122645416 Ether0.000683154
0x87fa2652580b49daa06c4aa226e783309f343851df13b79a91316c02cc76276e153 days 14 hrs ago0x94f64d3b1a40274f8fdc647bd21d32119596eadc  IN   0xcbf788b40d94cba28052e870298334dca837143a0 Ether0.000551781
[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
 Latest 25 Internal Txns, Click here To View More View All
ParentTxHash Block Age From To Value
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0xf142f1c7badc95fb438302d7cf0a5db426f8f7790 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xb05f4d26a747da0a5266faa950a9830b007530d1ffa83f2b9fddca76cfa8152d4302625115 days 18 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xdcad2ec689691189a47ce8869ac6bd4a59c6e897d9850921037c6f7d8ec43e6a4298033116 days 12 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0xf142f1c7badc95fb438302d7cf0a5db426f8f7790 Ether
0xdcad2ec689691189a47ce8869ac6bd4a59c6e897d9850921037c6f7d8ec43e6a4298033116 days 12 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xdcad2ec689691189a47ce8869ac6bd4a59c6e897d9850921037c6f7d8ec43e6a4298033116 days 12 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xdcad2ec689691189a47ce8869ac6bd4a59c6e897d9850921037c6f7d8ec43e6a4298033116 days 12 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xdcad2ec689691189a47ce8869ac6bd4a59c6e897d9850921037c6f7d8ec43e6a4298033116 days 12 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xdcad2ec689691189a47ce8869ac6bd4a59c6e897d9850921037c6f7d8ec43e6a4298033116 days 12 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xdcad2ec689691189a47ce8869ac6bd4a59c6e897d9850921037c6f7d8ec43e6a4298033116 days 12 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xdcad2ec689691189a47ce8869ac6bd4a59c6e897d9850921037c6f7d8ec43e6a4298033116 days 12 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xdcad2ec689691189a47ce8869ac6bd4a59c6e897d9850921037c6f7d8ec43e6a4298033116 days 12 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xdcad2ec689691189a47ce8869ac6bd4a59c6e897d9850921037c6f7d8ec43e6a4298033116 days 12 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
0xdcad2ec689691189a47ce8869ac6bd4a59c6e897d9850921037c6f7d8ec43e6a4298033116 days 12 hrs ago0xcbf788b40d94cba28052e870298334dca837143a0x829bcf8c990bd4c0de2a32a3a21068e0d154705d0 Ether
[ Download CSV Export  ] 
Warning: The Compiled Contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity) SolidityCompiler Bugs.

Contract Source Code Verified (Exact Match)
Contract Name: TripioRoomNightCustomer
Compiler Version: v0.4.24+commit.e67f0147
Optimization Enabled: Yes
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

pragma solidity ^0.4.24;

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 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 pure returns (string _name);

    /// @notice An abbreviated name for NFTs in this contract
    function symbol() external pure 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);
}


/// @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 _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 _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,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 payable;

    /// @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 payable;

    /// @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 payable;

    /// @notice Set or reaffirm the approved address for an NFT
    /// @dev The zero address indicates there is no approved address.
    /// @dev 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 payable;

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

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 *  from ERC721 asset contracts.
 */
contract ERC721Receiver {
    /**
    * @notice Handle the receipt of an NFT
    * @dev The ERC721 smart contract calls this function on the recipient
    *  after a `safetransfer`. This function MAY throw to revert and reject the
    *  transfer. This function MUST use 50,000 gas or less. Return of other
    *  than the magic value MUST result in the transaction being reverted.
    *  Note: the contract address is always the message sender.
    * @param _from The sending address
    * @param _tokenId The NFT identifier which is being transfered
    * @param _data Additional data with no specified format
    * @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
    */
    function onERC721Received(address _from, uint256 _tokenId, bytes _data) external returns(bytes4);
}

/**
 * Owned contract
 */
contract Owned {
    address public owner;
    address public newOwner;

    event OwnershipTransferred(address indexed from, address indexed to);

    /**
     * Constructor
     */
    constructor() public {
        owner = msg.sender;
    }

    /**
     * @dev Only the owner of contract
     */ 
    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
    
    /**
     * @dev transfer the ownership to other
     *      - Only the owner can operate
     */ 
    function transferOwnership(address _newOwner) public onlyOwner {
        newOwner = _newOwner;
    }

    /** 
     * @dev Accept the ownership from last owner
     */ 
    function acceptOwnership() public {
        require(msg.sender == newOwner);
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
        newOwner = address(0);
    }
}

contract TRNData is Owned {
    TripioRoomNightData dataSource;
    /**
     * Only the valid vendor and the vendor is valid
     */ 
    modifier onlyVendor {
        uint256 vendorId = dataSource.vendorIds(msg.sender);
        require(vendorId > 0);
        (,,,bool valid) = dataSource.getVendor(vendorId);
        require(valid);
        _;
    }

    /**
     * The vendor is valid
     */
    modifier vendorValid(address _vendor) {
        uint256 vendorId = dataSource.vendorIds(_vendor);
        require(vendorId > 0);
        (,,,bool valid) = dataSource.getVendor(vendorId);
        require(valid);
        _;
    }

    /**
     * The vendorId is valid
     */
    modifier vendorIdValid(uint256 _vendorId) {
        (,,,bool valid) = dataSource.getVendor(_vendorId);
        require(valid);
        _;
    }

    /**
     * Rate plan exist.
     */
    modifier ratePlanExist(uint256 _vendorId, uint256 _rpid) {
        (,,,bool valid) = dataSource.getVendor(_vendorId);
        require(valid);
        require(dataSource.ratePlanIsExist(_vendorId, _rpid));
        _;
    }
    
    /**
     * Token is valid
     */
    modifier validToken(uint256 _tokenId) {
        require(_tokenId > 0);
        require(dataSource.roomNightIndexToOwner(_tokenId) != address(0));
        _;
    }

    /**
     * Tokens are valid
     */
    modifier validTokenInBatch(uint256[] _tokenIds) {
        for(uint256 i = 0; i < _tokenIds.length; i++) {
            require(_tokenIds[i] > 0);
            require(dataSource.roomNightIndexToOwner(_tokenIds[i]) != address(0));
        }
        _;
    }

    /**
     * Whether the `_tokenId` can be transfered
     */
    modifier canTransfer(uint256 _tokenId) {
        address owner = dataSource.roomNightIndexToOwner(_tokenId);
        bool isOwner = (msg.sender == owner);
        bool isApproval = (msg.sender == dataSource.roomNightApprovals(_tokenId));
        bool isOperator = (dataSource.operatorApprovals(owner, msg.sender));
        require(isOwner || isApproval || isOperator);
        _;
    }

    /**
     * Whether the `_tokenIds` can be transfered
     */
    modifier canTransferInBatch(uint256[] _tokenIds) {
        for(uint256 i = 0; i < _tokenIds.length; i++) {
            address owner = dataSource.roomNightIndexToOwner(_tokenIds[i]);
            bool isOwner = (msg.sender == owner);
            bool isApproval = (msg.sender == dataSource.roomNightApprovals(_tokenIds[i]));
            bool isOperator = (dataSource.operatorApprovals(owner, msg.sender));
            require(isOwner || isApproval || isOperator);
        }
        _;
    }


    /**
     * Whether the `_tokenId` can be operated by `msg.sender`
     */
    modifier canOperate(uint256 _tokenId) {
        address owner = dataSource.roomNightIndexToOwner(_tokenId);
        bool isOwner = (msg.sender == owner);
        bool isOperator = (dataSource.operatorApprovals(owner, msg.sender));
        require(isOwner || isOperator);
        _;
    }

    /**
     * Whether the `_date` is valid(no hours, no seconds)
     */
    modifier validDate(uint256 _date) {
        require(_date > 0);
        require(dateIsLegal(_date));
        _;
    }

    /**
     * Whether the `_dates` are valid(no hours, no seconds)
     */
    modifier validDates(uint256[] _dates) {
        for(uint256 i = 0;i < _dates.length; i++) {
            require(_dates[i] > 0);
            require(dateIsLegal(_dates[i]));
        }
        _;
    }

    function dateIsLegal(uint256 _date) pure private returns(bool) {
        uint256 year = _date / 10000;
        uint256 mon = _date / 100 - year * 100;
        uint256 day = _date - mon * 100 - year * 10000;
        
        if(year < 1970 || mon <= 0 || mon > 12 || day <= 0 || day > 31)
            return false;

        if(4 == mon || 6 == mon || 9 == mon || 11 == mon){
            if (day == 31) {
                return false;
            }
        }
        if(((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {
            if(2 == mon && day > 29) {
                return false;
            }
        }else {
            if(2 == mon && day > 28){
                return false;
            }
        }
        return true;
    }
    /**
     * Constructor
     */
    constructor() public {

    }
}

contract TRNOwners is TRNData {
    /**
     * Constructor
     */
    constructor() public {

    }

    /**
     * Add room night token to `_owner`'s account(from the header)
     */
    function _pushRoomNight(address _owner, uint256 _rnid, bool _isVendor) internal {
        require(_owner != address(0));
        require(_rnid != 0);
        if (_isVendor) {
            dataSource.pushOrderOfVendor(_owner, _rnid, false);
        } else {
            dataSource.pushOrderOfOwner(_owner, _rnid, false);
        }
    }

    /**
     * Remove room night token from `_owner`'s account
     */
    function _removeRoomNight(address _owner, uint256 _rnid) internal {
        dataSource.removeOrderOfOwner(_owner, _rnid);
    }

    /**
     * @dev Returns all the room nights of the `msg.sender`(Customer)
     * @param _from The begin of room nights Id
     * @param _limit The total room nights 
     * @param _isVendor Is Vendor
     * @return Room nights of the `msg.sender` and the next vernier
     */
    function roomNightsOfOwner(uint256 _from, uint256 _limit, bool _isVendor) 
        external
        view 
        returns(uint256[], uint256) {
        if(_isVendor) {
            return dataSource.getOrdersOfVendor(msg.sender, _from, _limit, true);
        }else {
            return dataSource.getOrdersOfOwner(msg.sender, _from, _limit, true);
        }
    }

    /**
     * @dev Returns the room night infomation in detail
     * @param _rnid Room night id
     * @return Room night infomation in detail
     */
    function roomNight(uint256 _rnid) 
        external 
        view 
        returns(uint256 _vendorId,uint256 _rpid,uint256 _token,uint256 _price,uint256 _timestamp,uint256 _date,bytes32 _ipfs, string _name) {
        (_vendorId, _rpid, _token, _price, _timestamp, _date, _ipfs) = dataSource.roomnights(_rnid);
        (_name,,) = dataSource.getRatePlan(_vendorId, _rpid);
    }
}

library IPFSLib {
    bytes constant ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
    bytes constant HEX = "0123456789abcdef";

    /**
     * @dev Base58 encoding
     * @param _source Bytes data
     * @return Encoded bytes data
     */
    function base58Address(bytes _source) internal pure returns (bytes) {
        uint8[] memory digits = new uint8[](_source.length * 136/100 + 1);
        digits[0] = 0;
        uint8 digitlength = 1;
        for (uint i = 0; i < _source.length; ++i) {
            uint carry = uint8(_source[i]);
            for (uint j = 0; j<digitlength; ++j) {
                carry += uint(digits[j]) * 256;
                digits[j] = uint8(carry % 58);
                carry = carry / 58;
            }
            
            while (carry > 0) {
                digits[digitlength] = uint8(carry % 58);
                digitlength++;
                carry = carry / 58;
            }
        }
        return toAlphabet(reverse(truncate(digits, digitlength)));
    }

    /**
     * @dev Hex encoding, convert bytes32 data to hex string
     * @param _source Bytes32 data
     * @return hex string bytes
     */
    function hexAddress(bytes32 _source) internal pure returns(bytes) {
        uint256 value = uint256(_source);
        bytes memory result = "0000000000000000000000000000000000000000000000000000000000000000";
        uint8 index = 0;
        while(value > 0) {
            result[index] = HEX[value & 0xf];
            index++;
            value = value>>4;
        }
        bytes memory ipfsBytes = reverseBytes(result);
        return ipfsBytes;
    }

    /**
     * @dev Truncate `_array` by `_length`
     * @param _array The source array
     * @param _length The target length of the `_array`
     * @return The truncated array 
     */
    function truncate(uint8[] _array, uint8 _length) internal pure returns (uint8[]) {
        uint8[] memory output = new uint8[](_length);
        for (uint i = 0; i < _length; i++) {
            output[i] = _array[i];
        }
        return output;
    }
    
    /**
     * @dev Reverse `_input` array 
     * @param _input The source array 
     * @return The reversed array 
     */
    function reverse(uint8[] _input) internal pure returns (uint8[]) {
        uint8[] memory output = new uint8[](_input.length);
        for (uint i = 0; i < _input.length; i++) {
            output[i] = _input[_input.length - 1 - i];
        }
        return output;
    }

    /**
     * @dev Reverse `_input` bytes
     * @param _input The source bytes
     * @return The reversed bytes
     */
    function reverseBytes(bytes _input) private pure returns (bytes) {
        bytes memory output = new bytes(_input.length);
        for (uint8 i = 0; i < _input.length; i++) {
            output[i] = _input[_input.length-1-i];
        }
        return output;
    }
    
    /**
     * @dev Convert the indices to alphabet
     * @param _indices The indices of alphabet
     * @return The alphabets
     */
    function toAlphabet(uint8[] _indices) internal pure returns (bytes) {
        bytes memory output = new bytes(_indices.length);
        for (uint i = 0; i < _indices.length; i++) {
            output[i] = ALPHABET[_indices[i]];
        }
        return output;
    }

    /**
     * @dev Convert bytes32 to bytes
     * @param _input The source bytes32
     * @return The bytes
     */
    function toBytes(bytes32 _input) internal pure returns (bytes) {
        bytes memory output = new bytes(32);
        for (uint8 i = 0; i < 32; i++) {
            output[i] = _input[i];
        }
        return output;
    }

    /**
     * @dev Concat two bytes to one
     * @param _byteArray The first bytes
     * @param _byteArray2 The second bytes
     * @return The concated bytes
     */
    function concat(bytes _byteArray, bytes _byteArray2) internal pure returns (bytes) {
        bytes memory returnArray = new bytes(_byteArray.length + _byteArray2.length);
        for (uint16 i = 0; i < _byteArray.length; i++) {
            returnArray[i] = _byteArray[i];
        }
        for (i; i < (_byteArray.length + _byteArray2.length); i++) {
            returnArray[i] = _byteArray2[i - _byteArray.length];
        }
        return returnArray;
    }
}

contract TRNAsset is TRNData, ERC721Metadata {
    using IPFSLib for bytes;
    using IPFSLib for bytes32;

    /**
     * Constructor
     */
    constructor() public {
        
    }

    /**
     * @dev Descriptive name for Tripio's Room Night Token in this contract
     * @return The name of the contract
     */
    function name() external pure returns (string _name) {
        return "Tripio Room Night";
    }

    /**
     * @dev Abbreviated name for Tripio's Room Night Token in this contract
     * @return The simple name of the contract
     */
    function symbol() external pure returns (string _symbol) {
        return "TRN";
    }

    /**
     * @dev If `_tokenId` is not valid trows an exception otherwise return a URI which point to a JSON file like:
     *      {
     *       "name": "Identifies the asset to which this NFT represents",
     *       "description": "Describes the asset to which this NFT represents",
     *       "image": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive."
     *      }
     * @param _tokenId The RoomNight digital token
     * @return The digital token asset uri
     */
    function tokenURI(uint256 _tokenId) 
        external 
        view 
        validToken(_tokenId) 
        returns (string) { 
        bytes memory prefix = new bytes(2);
        prefix[0] = 0x12;
        prefix[1] = 0x20;
        (,,,,,,bytes32 ipfs) = dataSource.roomnights(_tokenId);
        bytes memory value = prefix.concat(ipfs.toBytes());
        bytes memory ipfsBytes = value.base58Address();
        bytes memory tokenBaseURIBytes = bytes(dataSource.tokenBaseURI());
        return string(tokenBaseURIBytes.concat(ipfsBytes));
    }
}

contract TRNOwnership is TRNOwners, ERC721 {
    /**
     * Constructor
     */
    constructor() public {

    }

    /**
     * This emits when ownership of any TRN changes by any mechanism.
     */
    event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);

    /**
     * This emits when the approved address for an RTN is changed or reaffirmed.
     */
    event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);

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

    /**
     * @dev Transfer the `_tokenId` to `_to` directly
     * @param _tokenId The room night token
     * @param _to The target owner
     */
    function _transfer(uint256 _tokenId, address _to) private {
        // Find the FROM address
        address from = dataSource.roomNightIndexToOwner(_tokenId);

        // Remove room night from the `from`
        _removeRoomNight(from, _tokenId);

        // Add room night to the `_to`
        _pushRoomNight(_to, _tokenId, false);

        // Change the owner of `_tokenId`
        // Remove approval of `_tokenId`
        dataSource.transferTokenTo(_tokenId, _to);

        // Emit Transfer event
        emit Transfer(from, _to, _tokenId);
    }

    function _safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes _data)
        private
        validToken(_tokenId)
        canTransfer(_tokenId) {
        // The token's owner is equal to `_from`
        address owner = dataSource.roomNightIndexToOwner(_tokenId);
        require(owner == _from);

        // Avoid `_to` is equal to address(0)
        require(_to != address(0));

        _transfer(_tokenId, _to);

        uint256 codeSize;
        assembly { codeSize := extcodesize(_to) }
        if (codeSize == 0) {
            return;
        }
        bytes4 retval = ERC721Receiver(_to).onERC721Received(_from, _tokenId, _data);
        require (retval == dataSource.ERC721_RECEIVED());
    }

    /**
     * @dev Count all TRNs assigned to an owner.
     *      Throw when `_owner` is equal to address(0)
     * @param _owner An address for whom to query the balance.
     * @return The number of TRNs owned by `_owner`.
     */
    function balanceOf(address _owner) external view returns (uint256) {
        require(_owner != address(0));
        return dataSource.balanceOf(_owner);
    }

    /**
     * @dev Find the owner of an TRN
     *      Throw unless `_tokenId` more than zero
     * @param _tokenId The identifier for an TRN
     * @return The address of the owner of the TRN
     */
    function ownerOf(uint256 _tokenId) external view returns (address) {
        require(_tokenId > 0);
        return dataSource.roomNightIndexToOwner(_tokenId);
    }

    /**
     * @dev Transfers the ownership of an TRN from one address to another address.
     *      Throws unless `msg.sender` is the current owner or an approved address for this TRN.
     *      Throws if `_tokenId` is not a valid TRN. 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 TRN
     * @param _to The new owner
     * @param _tokenId The TRN 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 payable {
        _safeTransferFrom(_from, _to, _tokenId, _data);
    }

    /**
     * @dev Same like safeTransferFrom with an extra data parameter, except this function just sets data to ""(empty)
     * @param _from The current owner of the TRN
     * @param _to The new owner
     * @param _tokenId The TRN to transfer
     */
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable {
        _safeTransferFrom(_from, _to, _tokenId, "");
    }

    /**
     * @dev Transfers the ownership of an TRN from one address to another address.
     *      Throws unless `msg.sender` is the current owner or an approved address for this TRN.
     *      Throws if `_tokenId` is not a valid TRN.
     * @param _from The current owner of the TRN
     * @param _to The new owner
     * @param _tokenId The TRN to transfer
     */
    function transferFrom(address _from, address _to, uint256 _tokenId) 
        external 
        payable
        validToken(_tokenId)
        canTransfer(_tokenId) {
        // The token's owner is equal to `_from`
        address owner = dataSource.roomNightIndexToOwner(_tokenId);
        require(owner == _from);

        // Avoid `_to` is equal to address(0)
        require(_to != address(0));

        _transfer(_tokenId, _to);
    }

    /**
     * @dev Transfers the ownership of TRNs from one address to another address.
     *      Throws unless `msg.sender` is the current owner or an approved address for this TRN.
     *      Throws if `_tokenIds` are not valid TRNs.
     * @param _from The current owner of the TRN
     * @param _to The new owner
     * @param _tokenIds The TRNs to transfer
     */
    function transferFromInBatch(address _from, address _to, uint256[] _tokenIds) 
        external
        payable
        validTokenInBatch(_tokenIds)
        canTransferInBatch(_tokenIds) {
        for(uint256 i = 0; i < _tokenIds.length; i++) {
            // The token's owner is equal to `_from`
            address owner = dataSource.roomNightIndexToOwner(_tokenIds[i]);
            require(owner == _from);

            // Avoid `_to` is equal to address(0)
            require(_to != address(0));

            _transfer(_tokenIds[i], _to);
        }
    }

    /**
     * @dev Set or reaffirm the approved address for an TRN.
     *      Throws unless `msg.sender` is the current TRN owner, or an authorized
     * @param _approved The new approved TRN controller
     * @param _tokenId The TRN to approve
     */
    function approve(address _approved, uint256 _tokenId) 
        external 
        payable 
        validToken(_tokenId)
        canOperate(_tokenId) {
        address owner = dataSource.roomNightIndexToOwner(_tokenId);
        
        dataSource.approveTokenTo(_tokenId, _approved);
        emit Approval(owner, _approved, _tokenId);
    }

    /**
     * @dev Enable or disable approval for a third party ("operator") to manage 
     *      all of `msg.sender`'s assets.
     *      Emits the ApprovalForAll event. 
     * @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 {
        require(_operator != address(0));
        dataSource.approveOperatorTo(_operator, msg.sender, _approved);
        emit ApprovalForAll(msg.sender, _operator, _approved);
    }

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

    /**
     * @dev Query if an address is an authorized operator for another address.
     * @param _owner The address that owns The TRNs
     * @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) {
        return dataSource.operatorApprovals(_owner, _operator);
    }
}


contract TRNSupportsInterface is TRNData, ERC165 {
    /**
     * Constructor
     */
    constructor() public {

    }

    /**
     * @dev Query if a contract implements an interface
     * @param interfaceID The interface identifier, as specified in ERC-165
     * @return true if the contract implements `interfaceID` 
     * and `interfaceID` is not 0xffffffff, false otherwise
     */
    function supportsInterface(bytes4 interfaceID) 
        external 
        view 
        returns (bool) {
        return ((interfaceID == dataSource.interfaceSignature_ERC165()) ||
        (interfaceID == dataSource.interfaceSignature_ERC721Metadata()) ||
        (interfaceID == dataSource.interfaceSignature_ERC721())) &&
        (interfaceID != 0xffffffff);
    }
}
/**
 * This utility library was forked from https://github.com/o0ragman0o/LibCLL
 */
library LinkedListLib {

    uint256 constant NULL = 0;
    uint256 constant HEAD = 0;
    bool constant PREV = false;
    bool constant NEXT = true;

    struct LinkedList {
        mapping (uint256 => mapping (bool => uint256)) list;
        uint256 length;
        uint256 index;
    }

    /**
     * @dev returns true if the list exists
     * @param self stored linked list from contract
     */
    function listExists(LinkedList storage self)
        internal
        view returns (bool) {
        return self.length > 0;
    }

    /**
     * @dev returns true if the node exists
     * @param self stored linked list from contract
     * @param _node a node to search for
     */
    function nodeExists(LinkedList storage self, uint256 _node)
        internal
        view returns (bool) {
        if (self.list[_node][PREV] == HEAD && self.list[_node][NEXT] == HEAD) {
            if (self.list[HEAD][NEXT] == _node) {
                return true;
            } else {
                return false;
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Returns the number of elements in the list
     * @param self stored linked list from contract
     */ 
    function sizeOf(LinkedList storage self) 
        internal 
        view 
        returns (uint256 numElements) {
        return self.length;
    }

    /**
     * @dev Returns the links of a node as a tuple
     * @param self stored linked list from contract
     * @param _node id of the node to get
     */
    function getNode(LinkedList storage self, uint256 _node)
        public 
        view 
        returns (bool, uint256, uint256) {
        if (!nodeExists(self,_node)) {
            return (false, 0, 0);
        } else {
            return (true, self.list[_node][PREV], self.list[_node][NEXT]);
        }
    }

    /**
     * @dev Returns the link of a node `_node` in direction `_direction`.
     * @param self stored linked list from contract
     * @param _node id of the node to step from
     * @param _direction direction to step in
     */
    function getAdjacent(LinkedList storage self, uint256 _node, bool _direction)
        public 
        view 
        returns (bool, uint256) {
        if (!nodeExists(self,_node)) {
            return (false,0);
        } else {
            return (true,self.list[_node][_direction]);
        }
    }

    /**
     * @dev Can be used before `insert` to build an ordered list
     * @param self stored linked list from contract
     * @param _node an existing node to search from, e.g. HEAD.
     * @param _value value to seek
     * @param _direction direction to seek in
     * @return next first node beyond '_node' in direction `_direction`
     */
    function getSortedSpot(LinkedList storage self, uint256 _node, uint256 _value, bool _direction)
        public 
        view 
        returns (uint256) {
        if (sizeOf(self) == 0) { 
            return 0; 
        }
        require((_node == 0) || nodeExists(self,_node));
        bool exists;
        uint256 next;
        (exists,next) = getAdjacent(self, _node, _direction);
        while  ((next != 0) && (_value != next) && ((_value < next) != _direction)) next = self.list[next][_direction];
        return next;
    }

    /**
     * @dev Creates a bidirectional link between two nodes on direction `_direction`
     * @param self stored linked list from contract
     * @param _node first node for linking
     * @param _link  node to link to in the _direction
     */
    function createLink(LinkedList storage self, uint256 _node, uint256 _link, bool _direction) 
        private {
        self.list[_link][!_direction] = _node;
        self.list[_node][_direction] = _link;
    }

    /**
     * @dev Insert node `_new` beside existing node `_node` in direction `_direction`.
     * @param self stored linked list from contract
     * @param _node existing node
     * @param _new  new node to insert
     * @param _direction direction to insert node in
     */
    function insert(LinkedList storage self, uint256 _node, uint256 _new, bool _direction) 
        internal 
        returns (bool) {
        if(!nodeExists(self,_new) && nodeExists(self,_node)) {
            uint256 c = self.list[_node][_direction];
            createLink(self, _node, _new, _direction);
            createLink(self, _new, c, _direction);
            self.length++;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev removes an entry from the linked list
     * @param self stored linked list from contract
     * @param _node node to remove from the list
     */
    function remove(LinkedList storage self, uint256 _node) 
        internal 
        returns (uint256) {
        if ((_node == NULL) || (!nodeExists(self,_node))) { 
            return 0; 
        }
        createLink(self, self.list[_node][PREV], self.list[_node][NEXT], NEXT);
        delete self.list[_node][PREV];
        delete self.list[_node][NEXT];
        self.length--;
        return _node;
    }

    /**
     * @dev pushes an enrty to the head of the linked list
     * @param self stored linked list from contract
     * @param _index The node Id
     * @param _direction push to the head (NEXT) or tail (PREV)
     */
    function add(LinkedList storage self, uint256 _index, bool _direction) 
        internal 
        returns (uint256) {
        insert(self, HEAD, _index, _direction);
        return self.index;
    }

    /**
     * @dev pushes an enrty to the head of the linked list
     * @param self stored linked list from contract
     * @param _direction push to the head (NEXT) or tail (PREV)
     */
    function push(LinkedList storage self, bool _direction) 
        internal 
        returns (uint256) {
        self.index++;
        insert(self, HEAD, self.index, _direction);
        return self.index;
    }

    /**
     * @dev pops the first entry from the linked list
     * @param self stored linked list from contract
     * @param _direction pop from the head (NEXT) or the tail (PREV)
     */
    function pop(LinkedList storage self, bool _direction) 
        internal 
        returns (uint256) {
        bool exists;
        uint256 adj;
        (exists,adj) = getAdjacent(self, HEAD, _direction);
        return remove(self, adj);
    }
}

contract TripioToken {
    string public name;
    string public symbol;
    uint8 public decimals;
    function transfer(address _to, uint256 _value) public returns (bool);
    function balanceOf(address who) public view returns (uint256);
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool);
}

contract TripioRoomNightData is Owned {
    using LinkedListLib for LinkedListLib.LinkedList;
    // Interface signature of erc165.
    // bytes4(keccak256("supportsInterface(bytes4)"))
    bytes4 constant public interfaceSignature_ERC165 = 0x01ffc9a7;

    // Interface signature of erc721 metadata.
    // bytes4(keccak256("name()")) ^ bytes4(keccak256("symbol()")) ^ bytes4(keccak256("tokenURI(uint256)"));
    bytes4 constant public interfaceSignature_ERC721Metadata = 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd;
        
    // Interface signature of erc721.
    // bytes4(keccak256("balanceOf(address)")) ^
    // bytes4(keccak256("ownerOf(uint256)")) ^
    // bytes4(keccak256("safeTransferFrom(address,address,uint256,bytes)")) ^
    // bytes4(keccak256("safeTransferFrom(address,address,uint256)")) ^
    // bytes4(keccak256("transferFrom(address,address,uint256)")) ^
    // bytes4(keccak256("approve(address,uint256)")) ^
    // bytes4(keccak256("setApprovalForAll(address,bool)")) ^
    // bytes4(keccak256("getApproved(uint256)")) ^
    // bytes4(keccak256("isApprovedForAll(address,address)"));
    bytes4 constant public interfaceSignature_ERC721 = 0x70a08231 ^ 0x6352211e ^ 0xb88d4fde ^ 0x42842e0e ^ 0x23b872dd ^ 0x095ea7b3 ^ 0xa22cb465 ^ 0x081812fc ^ 0xe985e9c5;

    // Base URI of token asset
    string public tokenBaseURI;

    // Authorized contracts
    struct AuthorizedContract {
        string name;
        address acontract;
    }
    mapping (address=>uint256) public authorizedContractIds;
    mapping (uint256 => AuthorizedContract) public authorizedContracts;
    LinkedListLib.LinkedList public authorizedContractList = LinkedListLib.LinkedList(0, 0);

    // Rate plan prices
    struct Price {
        uint16 inventory;       // Rate plan inventory
        bool init;              // Whether the price is initied
        mapping (uint256 => uint256) tokens;
    }

    // Vendor hotel RPs
    struct RatePlan {
        string name;            // Name of rate plan.
        uint256 timestamp;      // Create timestamp.
        bytes32 ipfs;           // The address of rate plan detail on IPFS.
        Price basePrice;        // The base price of rate plan
        mapping (uint256 => Price) prices;   // date -> Price
    }

    // Vendors
    struct Vendor {
        string name;            // Name of vendor.
        address vendor;         // Address of vendor.
        uint256 timestamp;      // Create timestamp.
        bool valid;             // Whether the vendor is valid(default is true)
        LinkedListLib.LinkedList ratePlanList;
        mapping (uint256=>RatePlan) ratePlans;
    }
    mapping (address => uint256) public vendorIds;
    mapping (uint256 => Vendor) vendors;
    LinkedListLib.LinkedList public vendorList = LinkedListLib.LinkedList(0, 0);

    // Supported digital currencies
    mapping (uint256 => address) public tokenIndexToAddress;
    LinkedListLib.LinkedList public tokenList = LinkedListLib.LinkedList(0, 0);

    // RoomNight tokens
    struct RoomNight {
        uint256 vendorId;
        uint256 rpid;
        uint256 token;          // The digital currency token 
        uint256 price;          // The digital currency price
        uint256 timestamp;      // Create timestamp.
        uint256 date;           // The checkin date
        bytes32 ipfs;           // The address of rate plan detail on IPFS.
    }
    RoomNight[] public roomnights;
    // rnid -> owner
    mapping (uint256 => address) public roomNightIndexToOwner;

    // Owner Account
    mapping (address => LinkedListLib.LinkedList) public roomNightOwners;

    // Vendor Account
    mapping (address => LinkedListLib.LinkedList) public roomNightVendors;

    // The authorized address for each TRN
    mapping (uint256 => address) public roomNightApprovals;

    // The authorized operators for each address
    mapping (address => mapping (address => bool)) public operatorApprovals;

    // The applications of room night redund
    mapping (address => mapping (uint256 => bool)) public refundApplications;

    // The signature of `onERC721Received(address,uint256,bytes)`
    // bytes4(keccak256("onERC721Received(address,uint256,bytes)"));
    bytes4 constant public ERC721_RECEIVED = 0xf0b9e5ba;

    /**
     * This emits when contract authorized
     */
    event ContractAuthorized(address _contract);

    /**
     * This emits when contract deauthorized
     */
    event ContractDeauthorized(address _contract);

    /**
     * The contract is valid
     */
    modifier authorizedContractValid(address _contract) {
        require(authorizedContractIds[_contract] > 0);
        _;
    }

    /**
     * The contract is valid
     */
    modifier authorizedContractIdValid(uint256 _cid) {
        require(authorizedContractList.nodeExists(_cid));
        _;
    }

    /**
     * Only the owner or authorized contract is valid
     */
    modifier onlyOwnerOrAuthorizedContract {
        require(msg.sender == owner || authorizedContractIds[msg.sender] > 0);
        _;
    }

    /**
     * Constructor
     */
    constructor() public {
        // Add one invalid RoomNight, avoid subscript 0
        roomnights.push(RoomNight(0, 0, 0, 0, 0, 0, 0));
    }

    /**
     * @dev Returns the node list and next node as a tuple
     * @param self stored linked list from contract
     * @param _node the begin id of the node to get
     * @param _limit the total nodes of one page
     * @param _direction direction to step in
     */
    function getNodes(LinkedListLib.LinkedList storage self, uint256 _node, uint256 _limit, bool _direction) 
        private
        view 
        returns (uint256[], uint256) {
        bool exists;
        uint256 i = 0;
        uint256 ei = 0;
        uint256 index = 0;
        uint256 count = _limit;
        if(count > self.length) {
            count = self.length;
        }
        (exists, i) = self.getAdjacent(_node, _direction);
        if(!exists || count == 0) {
            return (new uint256[](0), 0);
        }else {
            uint256[] memory temp = new uint256[](count);
            if(_node != 0) {
                index++;
                temp[0] = _node;
            }
            while (i != 0 && index < count) {
                temp[index] = i;
                (exists,i) = self.getAdjacent(i, _direction);
                index++;
            }
            ei = i;
            if(index < count) {
                uint256[] memory result = new uint256[](index);
                for(i = 0; i < index; i++) {
                    result[i] = temp[i];
                }
                return (result, ei);
            }else {
                return (temp, ei);
            }
        }
    }

    /**
     * @dev Authorize `_contract` to execute this contract's funs
     * @param _contract The contract address
     * @param _name The contract name
     */
    function authorizeContract(address _contract, string _name) 
        public 
        onlyOwner 
        returns(bool) {
        uint256 codeSize;
        assembly { codeSize := extcodesize(_contract) }
        require(codeSize != 0);
        // Not exists
        require(authorizedContractIds[_contract] == 0);

        // Add
        uint256 id = authorizedContractList.push(false);
        authorizedContractIds[_contract] = id;
        authorizedContracts[id] = AuthorizedContract(_name, _contract);

        // Event
        emit ContractAuthorized(_contract);
        return true;
    }

    /**
     * @dev Deauthorized `_contract` by address
     * @param _contract The contract address
     */
    function deauthorizeContract(address _contract) 
        public 
        onlyOwner
        authorizedContractValid(_contract)
        returns(bool) {
        uint256 id = authorizedContractIds[_contract];
        authorizedContractList.remove(id);
        authorizedContractIds[_contract] = 0;
        delete authorizedContracts[id];
        
        // Event 
        emit ContractDeauthorized(_contract);
        return true;
    }

    /**
     * @dev Deauthorized `_contract` by contract id
     * @param _cid The contract id
     */
    function deauthorizeContractById(uint256 _cid) 
        public
        onlyOwner
        authorizedContractIdValid(_cid)
        returns(bool) {
        address acontract = authorizedContracts[_cid].acontract;
        authorizedContractList.remove(_cid);
        authorizedContractIds[acontract] = 0;
        delete authorizedContracts[_cid];

        // Event 
        emit ContractDeauthorized(acontract);
        return true;
    }

    /**
     * @dev Get authorize contract ids by page
     * @param _from The begin authorize contract id
     * @param _limit How many authorize contract ids one page
     * @return The authorize contract ids and the next authorize contract id as tuple, the next page not exists when next eq 0
     */
    function getAuthorizeContractIds(uint256 _from, uint256 _limit) 
        external 
        view 
        returns(uint256[], uint256){
        return getNodes(authorizedContractList, _from, _limit, true);
    }

    /**
     * @dev Get authorize contract by id
     * @param _cid Then authorize contract id
     * @return The authorize contract info(_name, _acontract)
     */
    function getAuthorizeContract(uint256 _cid) 
        external 
        view 
        returns(string _name, address _acontract) {
        AuthorizedContract memory acontract = authorizedContracts[_cid]; 
        _name = acontract.name;
        _acontract = acontract.acontract;
    }

    /*************************************** GET ***************************************/

    /**
     * @dev Get the rate plan by `_vendorId` and `_rpid`
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     */
    function getRatePlan(uint256 _vendorId, uint256 _rpid) 
        public 
        view 
        returns (string _name, uint256 _timestamp, bytes32 _ipfs) {
        _name = vendors[_vendorId].ratePlans[_rpid].name;
        _timestamp = vendors[_vendorId].ratePlans[_rpid].timestamp;
        _ipfs = vendors[_vendorId].ratePlans[_rpid].ipfs;
    }

    /**
     * @dev Get the rate plan price by `_vendorId`, `_rpid`, `_date` and `_tokenId`
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @param _date The date desc (20180723)
     * @param _tokenId The digital token id
     * @return The price info(inventory, init, price)
     */
    function getPrice(uint256 _vendorId, uint256 _rpid, uint256 _date, uint256 _tokenId) 
        public
        view 
        returns(uint16 _inventory, bool _init, uint256 _price) {
        _inventory = vendors[_vendorId].ratePlans[_rpid].prices[_date].inventory;
        _init = vendors[_vendorId].ratePlans[_rpid].prices[_date].init;
        _price = vendors[_vendorId].ratePlans[_rpid].prices[_date].tokens[_tokenId];
        if(!_init) {
            // Get the base price
            _inventory = vendors[_vendorId].ratePlans[_rpid].basePrice.inventory;
            _price = vendors[_vendorId].ratePlans[_rpid].basePrice.tokens[_tokenId];
            _init = vendors[_vendorId].ratePlans[_rpid].basePrice.init;
        }
    }

    /**
     * @dev Get the rate plan prices by `_vendorId`, `_rpid`, `_dates` and `_tokenId`
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @param _dates The dates desc ([20180723,20180724,20180725])
     * @param _tokenId The digital token id
     * @return The price info(inventory, init, price)
     */
    function getPrices(uint256 _vendorId, uint256 _rpid, uint256[] _dates, uint256 _tokenId) 
        public
        view 
        returns(uint16[] _inventories, uint256[] _prices) {
        uint16[] memory inventories = new uint16[](_dates.length);
        uint256[] memory prices = new uint256[](_dates.length);
        uint256 date;
        for(uint256 i = 0; i < _dates.length; i++) {
            date = _dates[i];
            uint16 inventory = vendors[_vendorId].ratePlans[_rpid].prices[date].inventory;
            bool init = vendors[_vendorId].ratePlans[_rpid].prices[date].init;
            uint256 price = vendors[_vendorId].ratePlans[_rpid].prices[date].tokens[_tokenId];
            if(!init) {
                // Get the base price
                inventory = vendors[_vendorId].ratePlans[_rpid].basePrice.inventory;
                price = vendors[_vendorId].ratePlans[_rpid].basePrice.tokens[_tokenId];
                init = vendors[_vendorId].ratePlans[_rpid].basePrice.init;
            }
            inventories[i] = inventory;
            prices[i] = price;
        }
        return (inventories, prices);
    }

    /**
     * @dev Get the inventory by  by `_vendorId`, `_rpid` and `_date`
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @param _date The date desc (20180723)
     * @return The inventory info(inventory, init)
     */
    function getInventory(uint256 _vendorId, uint256 _rpid, uint256 _date) 
        public
        view 
        returns(uint16 _inventory, bool _init) {
        _inventory = vendors[_vendorId].ratePlans[_rpid].prices[_date].inventory;
        _init = vendors[_vendorId].ratePlans[_rpid].prices[_date].init;
        if(!_init) {
            // Get the base price
            _inventory = vendors[_vendorId].ratePlans[_rpid].basePrice.inventory;
        }
    }

    /**
     * @dev Whether the rate plan is exist
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @return If the rate plan of the vendor is exist returns true otherwise return false
     */
    function ratePlanIsExist(uint256 _vendorId, uint256 _rpid) 
        public 
        view 
        returns (bool) {
        return vendors[_vendorId].ratePlanList.nodeExists(_rpid);
    }

    /**
     * @dev Get orders of owner by page
     * @param _owner The owner address
     * @param _from The begin id of the node to get
     * @param _limit The total nodes of one page
     * @param _direction Direction to step in
     * @return The order ids and the next id
     */
    function getOrdersOfOwner(address _owner, uint256 _from, uint256 _limit, bool _direction) 
        public 
        view 
        returns (uint256[], uint256) {
        return getNodes(roomNightOwners[_owner], _from, _limit, _direction);
    }

    /**
     * @dev Get orders of vendor by page
     * @param _owner The vendor address
     * @param _from The begin id of the node to get
     * @param _limit The total nodes of on page
     * @param _direction Direction to step in 
     * @return The order ids and the next id
     */
    function getOrdersOfVendor(address _owner, uint256 _from, uint256 _limit, bool _direction) 
        public 
        view 
        returns (uint256[], uint256) {
        return getNodes(roomNightVendors[_owner], _from, _limit, _direction);
    }

    /**
     * @dev Get the token count of somebody 
     * @param _owner The owner of token
     * @return The token count of `_owner`
     */
    function balanceOf(address _owner) 
        public 
        view 
        returns(uint256) {
        return roomNightOwners[_owner].length;
    }

    /**
     * @dev Get rate plan ids of `_vendorId`
     * @param _from The begin id of the node to get
     * @param _limit The total nodes of on page
     * @param _direction Direction to step in 
     * @return The rate plan ids and the next id
     */
    function getRatePlansOfVendor(uint256 _vendorId, uint256 _from, uint256 _limit, bool _direction) 
        public 
        view 
        returns(uint256[], uint256) {
        return getNodes(vendors[_vendorId].ratePlanList, _from, _limit, _direction);
    }

    /**
     * @dev Get token ids
     * @param _from The begin id of the node to get
     * @param _limit The total nodes of on page
     * @param _direction Direction to step in 
     * @return The token ids and the next id
     */
    function getTokens(uint256 _from, uint256 _limit, bool _direction) 
        public 
        view 
        returns(uint256[], uint256) {
        return getNodes(tokenList, _from, _limit, _direction);
    }

    /**
     * @dev Get token Info
     * @param _tokenId The token id
     * @return The token info(symbol, name, decimals)
     */
    function getToken(uint256 _tokenId)
        public 
        view 
        returns(string _symbol, string _name, uint8 _decimals, address _token) {
        _token = tokenIndexToAddress[_tokenId];
        TripioToken tripio = TripioToken(_token);
        _symbol = tripio.symbol();
        _name = tripio.name();
        _decimals = tripio.decimals();
    }

    /**
     * @dev Get vendor ids
     * @param _from The begin id of the node to get
     * @param _limit The total nodes of on page
     * @param _direction Direction to step in 
     * @return The vendor ids and the next id
     */
    function getVendors(uint256 _from, uint256 _limit, bool _direction) 
        public 
        view 
        returns(uint256[], uint256) {
        return getNodes(vendorList, _from, _limit, _direction);
    }

    /**
     * @dev Get the vendor infomation by vendorId
     * @param _vendorId The vendor id
     * @return The vendor infomation(name, vendor, timestamp, valid)
     */
    function getVendor(uint256 _vendorId) 
        public 
        view 
        returns(string _name, address _vendor,uint256 _timestamp, bool _valid) {
        _name = vendors[_vendorId].name;
        _vendor = vendors[_vendorId].vendor;
        _timestamp = vendors[_vendorId].timestamp;
        _valid = vendors[_vendorId].valid;
    }

    /*************************************** SET ***************************************/
    /**
     * @dev Update base uri of token metadata
     * @param _tokenBaseURI The base uri
     */
    function updateTokenBaseURI(string _tokenBaseURI) 
        public 
        onlyOwnerOrAuthorizedContract {
        tokenBaseURI = _tokenBaseURI;
    }

    /**
     * @dev Push order to user's order list
     * @param _owner The buyer address
     * @param _rnid The room night order id
     * @param _direction direction to step in
     */
    function pushOrderOfOwner(address _owner, uint256 _rnid, bool _direction) 
        public 
        onlyOwnerOrAuthorizedContract {
        if(!roomNightOwners[_owner].listExists()) {
            roomNightOwners[_owner] = LinkedListLib.LinkedList(0, 0);
        }
        roomNightOwners[_owner].add(_rnid, _direction);
    }

    /**
     * @dev Remove order from owner's order list
     * @param _owner The owner address
     * @param _rnid The room night order id
     */
    function removeOrderOfOwner(address _owner, uint _rnid) 
        public 
        onlyOwnerOrAuthorizedContract {
        require(roomNightOwners[_owner].nodeExists(_rnid));
        roomNightOwners[_owner].remove(_rnid);
    }

    /**
     * @dev Push order to the vendor's order list
     * @param _vendor The vendor address
     * @param _rnid The room night order id
     * @param _direction direction to step in
     */
    function pushOrderOfVendor(address _vendor, uint256 _rnid, bool _direction) 
        public 
        onlyOwnerOrAuthorizedContract {
        if(!roomNightVendors[_vendor].listExists()) {
            roomNightVendors[_vendor] = LinkedListLib.LinkedList(0, 0);
        }
        roomNightVendors[_vendor].add(_rnid, _direction);
    }

    /**
     * @dev Remove order from vendor's order list
     * @param _vendor The vendor address
     * @param _rnid The room night order id
     */
    function removeOrderOfVendor(address _vendor, uint256 _rnid) 
        public 
        onlyOwnerOrAuthorizedContract {
        require(roomNightVendors[_vendor].nodeExists(_rnid));
        roomNightVendors[_vendor].remove(_rnid);
    }

    /**
     * @dev Transfer token to somebody
     * @param _tokenId The token id 
     * @param _to The target owner of the token
     */
    function transferTokenTo(uint256 _tokenId, address _to) 
        public 
        onlyOwnerOrAuthorizedContract {
        roomNightIndexToOwner[_tokenId] = _to;
        roomNightApprovals[_tokenId] = address(0);
    }

    /**
     * @dev Approve `_to` to operate the `_tokenId`
     * @param _tokenId The token id
     * @param _to Somebody to be approved
     */
    function approveTokenTo(uint256 _tokenId, address _to) 
        public 
        onlyOwnerOrAuthorizedContract {
        roomNightApprovals[_tokenId] = _to;
    }

    /**
     * @dev Approve `_operator` to operate all the Token of `_to`
     * @param _operator The operator to be approved
     * @param _to The owner of tokens to be operate
     * @param _approved Approved or not
     */
    function approveOperatorTo(address _operator, address _to, bool _approved) 
        public 
        onlyOwnerOrAuthorizedContract {
        operatorApprovals[_to][_operator] = _approved;
    } 

    /**
     * @dev Update base price of rate plan
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @param _tokenId The digital token id
     * @param _price The price to be updated
     */
    function updateBasePrice(uint256 _vendorId, uint256 _rpid, uint256 _tokenId, uint256 _price)
        public 
        onlyOwnerOrAuthorizedContract {
        vendors[_vendorId].ratePlans[_rpid].basePrice.init = true;
        vendors[_vendorId].ratePlans[_rpid].basePrice.tokens[_tokenId] = _price;
    }

    /**
     * @dev Update base inventory of rate plan 
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @param _inventory The inventory to be updated
     */
    function updateBaseInventory(uint256 _vendorId, uint256 _rpid, uint16 _inventory)
        public 
        onlyOwnerOrAuthorizedContract {
        vendors[_vendorId].ratePlans[_rpid].basePrice.inventory = _inventory;
    }

    /**
     * @dev Update price by `_vendorId`, `_rpid`, `_date`, `_tokenId` and `_price`
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @param _date The date desc (20180723)
     * @param _tokenId The digital token id
     * @param _price The price to be updated
     */
    function updatePrice(uint256 _vendorId, uint256 _rpid, uint256 _date, uint256 _tokenId, uint256 _price)
        public
        onlyOwnerOrAuthorizedContract {
        if (vendors[_vendorId].ratePlans[_rpid].prices[_date].init) {
            vendors[_vendorId].ratePlans[_rpid].prices[_date].tokens[_tokenId] = _price;
        } else {
            vendors[_vendorId].ratePlans[_rpid].prices[_date] = Price(0, true);
            vendors[_vendorId].ratePlans[_rpid].prices[_date].tokens[_tokenId] = _price;
        }
    }

    /**
     * @dev Update inventory by `_vendorId`, `_rpid`, `_date`, `_inventory`
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @param _date The date desc (20180723)
     * @param _inventory The inventory to be updated
     */
    function updateInventories(uint256 _vendorId, uint256 _rpid, uint256 _date, uint16 _inventory)
        public 
        onlyOwnerOrAuthorizedContract {
        if (vendors[_vendorId].ratePlans[_rpid].prices[_date].init) {
            vendors[_vendorId].ratePlans[_rpid].prices[_date].inventory = _inventory;
        } else {
            vendors[_vendorId].ratePlans[_rpid].prices[_date] = Price(_inventory, true);
        }
    }

    /**
     * @dev Reduce inventories
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @param _date The date desc (20180723)
     * @param _inventory The amount to be reduced
     */
    function reduceInventories(uint256 _vendorId, uint256 _rpid, uint256 _date, uint16 _inventory) 
        public  
        onlyOwnerOrAuthorizedContract {
        uint16 a = 0;
        if(vendors[_vendorId].ratePlans[_rpid].prices[_date].init) {
            a = vendors[_vendorId].ratePlans[_rpid].prices[_date].inventory;
            require(_inventory <= a);
            vendors[_vendorId].ratePlans[_rpid].prices[_date].inventory = a - _inventory;
        }else if(vendors[_vendorId].ratePlans[_rpid].basePrice.init){
            a = vendors[_vendorId].ratePlans[_rpid].basePrice.inventory;
            require(_inventory <= a);
            vendors[_vendorId].ratePlans[_rpid].basePrice.inventory = a - _inventory;
        }
    }

    /**
     * @dev Add inventories
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @param _date The date desc (20180723)
     * @param _inventory The amount to be add
     */
    function addInventories(uint256 _vendorId, uint256 _rpid, uint256 _date, uint16 _inventory) 
        public  
        onlyOwnerOrAuthorizedContract {
        uint16 c = 0;
        if(vendors[_vendorId].ratePlans[_rpid].prices[_date].init) {
            c = _inventory + vendors[_vendorId].ratePlans[_rpid].prices[_date].inventory;
            require(c >= _inventory);
            vendors[_vendorId].ratePlans[_rpid].prices[_date].inventory = c;
        }else if(vendors[_vendorId].ratePlans[_rpid].basePrice.init) {
            c = _inventory + vendors[_vendorId].ratePlans[_rpid].basePrice.inventory;
            require(c >= _inventory);
            vendors[_vendorId].ratePlans[_rpid].basePrice.inventory = c;
        }
    }

    /**
     * @dev Update inventory and price by `_vendorId`, `_rpid`, `_date`, `_tokenId`, `_price` and `_inventory`
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @param _date The date desc (20180723)
     * @param _tokenId The digital token id
     * @param _price The price to be updated
     * @param _inventory The inventory to be updated
     */
    function updatePriceAndInventories(uint256 _vendorId, uint256 _rpid, uint256 _date, uint256 _tokenId, uint256 _price, uint16 _inventory)
        public 
        onlyOwnerOrAuthorizedContract {
        if (vendors[_vendorId].ratePlans[_rpid].prices[_date].init) {
            vendors[_vendorId].ratePlans[_rpid].prices[_date].inventory = _inventory;
            vendors[_vendorId].ratePlans[_rpid].prices[_date].tokens[_tokenId] = _price;
        } else {
            vendors[_vendorId].ratePlans[_rpid].prices[_date] = Price(_inventory, true);
            vendors[_vendorId].ratePlans[_rpid].prices[_date].tokens[_tokenId] = _price;
        }
    }

    /**
     * @dev Push rate plan to `_vendorId`'s rate plan list
     * @param _vendorId The vendor id
     * @param _name The name of rate plan
     * @param _ipfs The rate plan IPFS address
     * @param _direction direction to step in
     */
    function pushRatePlan(uint256 _vendorId, string _name, bytes32 _ipfs, bool _direction) 
        public 
        onlyOwnerOrAuthorizedContract
        returns(uint256) {
        RatePlan memory rp = RatePlan(_name, uint256(now), _ipfs, Price(0, false));
        
        uint256 id = vendors[_vendorId].ratePlanList.push(_direction);
        vendors[_vendorId].ratePlans[id] = rp;
        return id;
    }

    /**
     * @dev Remove rate plan of `_vendorId` by `_rpid`
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     */
    function removeRatePlan(uint256 _vendorId, uint256 _rpid) 
        public 
        onlyOwnerOrAuthorizedContract {
        delete vendors[_vendorId].ratePlans[_rpid];
        vendors[_vendorId].ratePlanList.remove(_rpid);
    }

    /**
     * @dev Update `_rpid` of `_vendorId` by `_name` and `_ipfs`
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @param _name The rate plan name
     * @param _ipfs The rate plan IPFS address
     */
    function updateRatePlan(uint256 _vendorId, uint256 _rpid, string _name, bytes32 _ipfs)
        public 
        onlyOwnerOrAuthorizedContract {
        vendors[_vendorId].ratePlans[_rpid].ipfs = _ipfs;
        vendors[_vendorId].ratePlans[_rpid].name = _name;
    }
    
    /**
     * @dev Push token contract to the token list
     * @param _direction direction to step in
     */
    function pushToken(address _contract, bool _direction)
        public 
        onlyOwnerOrAuthorizedContract 
        returns(uint256) {
        uint256 id = tokenList.push(_direction);
        tokenIndexToAddress[id] = _contract;
        return id;
    }

    /**
     * @dev Remove token by `_tokenId`
     * @param _tokenId The digital token id
     */
    function removeToken(uint256 _tokenId) 
        public 
        onlyOwnerOrAuthorizedContract {
        delete tokenIndexToAddress[_tokenId];
        tokenList.remove(_tokenId);
    }

    /**
     * @dev Generate room night token
     * @param _vendorId The vendor id
     * @param _rpid The rate plan id
     * @param _date The date desc (20180723)
     * @param _token The token id
     * @param _price The token price
     * @param _ipfs The rate plan IPFS address
     */
    function generateRoomNightToken(uint256 _vendorId, uint256 _rpid, uint256 _date, uint256 _token, uint256 _price, bytes32 _ipfs)
        public 
        onlyOwnerOrAuthorizedContract 
        returns(uint256) {
        roomnights.push(RoomNight(_vendorId, _rpid, _token, _price, now, _date, _ipfs));

        // Give the token to `_customer`
        uint256 rnid = uint256(roomnights.length - 1);
        return rnid;
    }

    /**
     * @dev Update refund applications
     * @param _buyer The room night token holder
     * @param _rnid The room night token id
     * @param _isRefund Is redund or not
     */
    function updateRefundApplications(address _buyer, uint256 _rnid, bool _isRefund) 
        public 
        onlyOwnerOrAuthorizedContract {
        refundApplications[_buyer][_rnid] = _isRefund;
    }

    /**
     * @dev Push vendor info to the vendor list
     * @param _name The name of vendor
     * @param _vendor The vendor address
     * @param _direction direction to step in
     */
    function pushVendor(string _name, address _vendor, bool _direction)
        public 
        onlyOwnerOrAuthorizedContract 
        returns(uint256) {
        uint256 id = vendorList.push(_direction);
        vendorIds[_vendor] = id;
        vendors[id] = Vendor(_name, _vendor, uint256(now), true, LinkedListLib.LinkedList(0, 0));
        return id;
    }

    /**
     * @dev Remove vendor from vendor list
     * @param _vendorId The vendor id
     */
    function removeVendor(uint256 _vendorId) 
        public 
        onlyOwnerOrAuthorizedContract {
        vendorList.remove(_vendorId);
        address vendor = vendors[_vendorId].vendor;
        vendorIds[vendor] = 0;
        delete vendors[_vendorId];
    }

    /**
     * @dev Make vendor valid or invalid
     * @param _vendorId The vendor id
     * @param _valid The vendor is valid or not
     */
    function updateVendorValid(uint256 _vendorId, bool _valid)
        public 
        onlyOwnerOrAuthorizedContract {
        vendors[_vendorId].valid = _valid;
    }

    /**
     * @dev Modify vendor's name
     * @param _vendorId The vendor id
     * @param _name Then vendor name
     */
    function updateVendorName(uint256 _vendorId, string _name)
        public 
        onlyOwnerOrAuthorizedContract {
        vendors[_vendorId].name = _name;
    }
}



contract TRNTransactions is TRNOwners {
    /**
     * Constructor
     */
    constructor() public {

    }

    /**
     * This emits when rate plan is bought in batch
     */
    event BuyInBatch(address indexed _customer, address indexed _vendor, uint256 indexed _rpid, uint256[] _dates, uint256 _token);

    /**
     * This emits when token refund is applied 
     */
    event ApplyRefund(address _customer, uint256 indexed _rnid, bool _isRefund);

    /**
     * This emits when refunded
     */
    event Refund(address _vendor, uint256 _rnid);

    /**
     * @dev Complete the buy transaction,
     *      The inventory minus one and the room night token transfer to customer
     * @param _vendorId The vendor account
     * @param _rpid The vendor's rate plan id
     * @param _date The booking date
     * @param _customer The customer account
     * @param _token The token Id
     */
    function _buy(uint256 _vendorId, uint256 _rpid, uint256 _date, address _customer, uint256 _token) private {
        // Product room night token
        (,,uint256 _price) = dataSource.getPrice(_vendorId, _rpid, _date, _token);
        (,,bytes32 _ipfs) = dataSource.getRatePlan(_vendorId, _rpid);
        uint256 rnid = dataSource.generateRoomNightToken(_vendorId, _rpid, _date, _token, _price, _ipfs);

        // Give the token to `_customer`
        dataSource.transferTokenTo(rnid, _customer);

        // Record the token to `_customer` account
        _pushRoomNight(_customer, rnid, false);

        // Record the token to `_vendor` account
        (,address vendor,,) = dataSource.getVendor(_vendorId);
        _pushRoomNight(vendor, rnid, true);

        // The inventory minus one
        dataSource.reduceInventories(_vendorId, _rpid, _date, 1);
    }

    /**
     * @dev Complete the buy transaction in batch,
     *      The inventory minus one and the room night token transfer to customer
     * @param _vendorId The vendor account
     * @param _vendor Then vendor address
     * @param _rpid The vendor's rate plan id
     * @param _dates The booking date
     * @param _token The token Id
     */
    function _buyInBatch(uint256 _vendorId, address _vendor, uint256 _rpid, uint256[] _dates, uint256 _token) private returns(bool) {
        (uint16[] memory inventories, uint256[] memory values) = dataSource.getPrices(_vendorId, _rpid, _dates, _token);
        uint256 totalValues = 0;
        for(uint256 i = 0; i < _dates.length; i++) {
            if(inventories[i] == 0 || values[i] == 0) {
                return false;
            }
            totalValues += values[i];
            // Transfer the room night to `msg.sender`
            _buy(_vendorId, _rpid, _dates[i], msg.sender, _token);
        }
        
        if (_token == 0) {
            // By through ETH
            require(msg.value == totalValues);

            // Transfer the ETH to `_vendor`
            _vendor.transfer(totalValues);
        } else {
            // By through other digital token
            address tokenAddress = dataSource.tokenIndexToAddress(_token);
            require(tokenAddress != address(0));

            // This contract transfer `price.trio` from `msg.sender` account
            TripioToken tripio = TripioToken(tokenAddress);
            tripio.transferFrom(msg.sender, _vendor, totalValues);
        }
        return true;
    }

    /**
     * Complete the refund transaction
     * Remove the `_rnid` from the owner account and the inventory plus one
     */
    function _refund(uint256 _rnid, uint256 _vendorId, uint256 _rpid, uint256 _date) private {
        // Remove the `_rnid` from the owner
        _removeRoomNight(dataSource.roomNightIndexToOwner(_rnid), _rnid);

        // The inventory plus one
        dataSource.addInventories(_vendorId, _rpid, _date, 1);

        // Change the owner of `_rnid`
        dataSource.transferTokenTo(_rnid, address(0));
    }

    /**
     * @dev By room nigth in batch through ETH(`_token` == 0) or other digital token(`_token != 0`)
     *      Throw when `_rpid` not exist
     *      Throw unless each inventory more than zero
     *      Throw unless `msg.value` equal to `price.eth`
     *      This method is payable, can accept ETH transfer
     * @param _vendorId The vendor Id
     * @param _rpid The _vendor's rate plan id
     * @param _dates The booking dates
     * @param _token The digital currency token 
     */
    function buyInBatch(uint256 _vendorId, uint256 _rpid, uint256[] _dates, uint256 _token) 
        external
        payable
        ratePlanExist(_vendorId, _rpid)
        validDates(_dates)
        returns(bool) {
        
        (,address vendor,,) = dataSource.getVendor(_vendorId);
        
        bool result = _buyInBatch(_vendorId, vendor, _rpid, _dates, _token);
        
        require(result);

        // Event
        emit BuyInBatch(msg.sender, vendor, _rpid, _dates, _token);
        return true;
    }

    /**
     * @dev Apply room night refund
     *      Throw unless `_rnid` is valid
     *      Throw unless `_rnid` can transfer
     * @param _rnid room night identifier
     * @param _isRefund if `true` the `_rnid` can transfer else not
     */
    function applyRefund(uint256 _rnid, bool _isRefund) 
        external
        validToken(_rnid)
        canTransfer(_rnid)
        returns(bool) {
        dataSource.updateRefundApplications(msg.sender, _rnid, _isRefund);

        // Event
        emit ApplyRefund(msg.sender, _rnid, _isRefund);
        return true;
    }

    /**
     * @dev Whether the `_rnid` is in refund applications
     * @param _rnid room night identifier
     */
    function isRefundApplied(uint256 _rnid) 
        external
        view
        validToken(_rnid) returns(bool) {
        return dataSource.refundApplications(dataSource.roomNightIndexToOwner(_rnid), _rnid);
    }

    /**
     * @dev Refund through ETH or other digital token, give the room night ETH/TOKEN to customer and take back inventory
     *      Throw unless `_rnid` is valid
     *      Throw unless `msg.sender` is vendor
     *      Throw unless the refund application is true
     *      Throw unless the `msg.value` is equal to `roomnight.eth`
     * @param _rnid room night identifier
     */
    function refund(uint256 _rnid) 
        external
        payable
        validToken(_rnid) 
        returns(bool) {
        // Refund application is true
        require(dataSource.refundApplications(dataSource.roomNightIndexToOwner(_rnid), _rnid));

        // The `msg.sender` is the vendor of the room night.
        (uint256 vendorId,uint256 rpid,uint256 token,uint256 price,,uint256 date,) = dataSource.roomnights(_rnid);
        (,address vendor,,) = dataSource.getVendor(vendorId);
        require(msg.sender == vendor);

        address ownerAddress = dataSource.roomNightIndexToOwner(_rnid);

        if (token == 0) {
            // Refund by ETH

            // The `msg.sender` is equal to `roomnight.eth`
            uint256 value = price;
            require(msg.value >= value);

            // Transfer the ETH to roomnight's owner
            ownerAddress.transfer(value);
        } else {
            // Refund  by TRIO

            // The `roomnight.trio` is more than zero
            require(price > 0);

            // This contract transfer `price.trio` from `msg.sender` account
            TripioToken tripio = TripioToken(dataSource.tokenIndexToAddress(token));
            tripio.transferFrom(msg.sender, ownerAddress, price);
        }
        // Refund
        _refund(_rnid, vendorId, rpid, date);

        // Event 
        emit Refund(msg.sender, _rnid);
        return true;
    }
}

contract TripioRoomNightCustomer is TRNAsset, TRNSupportsInterface, TRNOwnership, TRNTransactions {
    /**
     * Constructor
     */
    constructor(address _dataSource) public {
        // Init the data source
        dataSource = TripioRoomNightData(_dataSource);
    }

    /**
     * @dev Withdraw ETH balance from contract account, the balance will transfer to the contract owner
     */
    function withdrawBalance() external onlyOwner {
        owner.transfer(address(this).balance);
    }

    /**
     * @dev Withdraw other TOKEN balance from contract account, the balance will transfer to the contract owner
     * @param _token The TOKEN id
     */
    function withdrawTokenId(uint _token) external onlyOwner {
        TripioToken tripio = TripioToken(dataSource.tokenIndexToAddress(_token));
        uint256 tokens = tripio.balanceOf(address(this));
        tripio.transfer(owner, tokens);
    }

    /**
     * @dev Withdraw other TOKEN balance from contract account, the balance will transfer to the contract owner
     * @param _tokenAddress The TOKEN address
     */
    function withdrawToken(address _tokenAddress) external onlyOwner {
        TripioToken tripio = TripioToken(_tokenAddress);
        uint256 tokens = tripio.balanceOf(address(this));
        tripio.transfer(owner, tokens);
    }

    /**
     * @dev Destory the contract
     */
    function destroy() external onlyOwner {
        selfdestruct(owner);
    }

    function() external payable {

    }
}

    Contract ABI  
[{"constant":true,"inputs":[{"name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"_name","type":"string"}],"payable":false,"stateMutability":"pure","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":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenIds","type":"uint256[]"}],"name":"transferFromInBatch","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_rnid","type":"uint256"}],"name":"refund","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"withdrawBalance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_rnid","type":"uint256"}],"name":"isRefundApplied","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_rnid","type":"uint256"}],"name":"roomNight","outputs":[{"name":"_vendorId","type":"uint256"},{"name":"_rpid","type":"uint256"},{"name":"_token","type":"uint256"},{"name":"_price","type":"uint256"},{"name":"_timestamp","type":"uint256"},{"name":"_date","type":"uint256"},{"name":"_ipfs","type":"bytes32"},{"name":"_name","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"name":"","type":"address"}],"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":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"destroy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenAddress","type":"address"}],"name":"withdrawToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_from","type":"uint256"},{"name":"_limit","type":"uint256"},{"name":"_isVendor","type":"bool"}],"name":"roomNightsOfOwner","outputs":[{"name":"","type":"uint256[]"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"_symbol","type":"string"}],"payable":false,"stateMutability":"pure","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":"_rnid","type":"uint256"},{"name":"_isRefund","type":"bool"}],"name":"applyRefund","outputs":[{"name":"","type":"bool"}],"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":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"uint256"}],"name":"withdrawTokenId","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":"newOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_vendorId","type":"uint256"},{"name":"_rpid","type":"uint256"},{"name":"_dates","type":"uint256[]"},{"name":"_token","type":"uint256"}],"name":"buyInBatch","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","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":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_dataSource","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_customer","type":"address"},{"indexed":true,"name":"_vendor","type":"address"},{"indexed":true,"name":"_rpid","type":"uint256"},{"indexed":false,"name":"_dates","type":"uint256[]"},{"indexed":false,"name":"_token","type":"uint256"}],"name":"BuyInBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_customer","type":"address"},{"indexed":true,"name":"_rnid","type":"uint256"},{"indexed":false,"name":"_isRefund","type":"bool"}],"name":"ApplyRefund","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_vendor","type":"address"},{"indexed":false,"name":"_rnid","type":"uint256"}],"name":"Refund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_approved","type":"address"},{"indexed":false,"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"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"}]

  Contract Creation Code Switch To Opcodes View
608060405234801561001057600080fd5b506040516020806148dc833981016040525160008054600160a060020a0319908116331790915560028054600160a060020a039093169290911691909117905561487d8061005f6000396000f3006080604052600436106101505763ffffffff60e060020a60003504166301ffc9a7811461015257806306fdde0314610188578063081812fc14610212578063095ea7b31461024657806311a767291461025d57806323b872dd14610285578063278ecde1146102a257806342842e0e146102ad5780635fd8c710146102ca578063612ef6e9146102df578063628c225c146102f75780636352211e146103c057806370a08231146103d857806379ba50971461040b57806383197ef0146104205780638947606914610435578063899f107d146104565780638da5cb5b146104d157806395d89b41146104e6578063a22cb465146104fb578063b08e0d3e14610521578063b88d4fde1461053e578063bb6ad6ef1461056a578063c87b56dd14610582578063d4ee1d901461059a578063dfd17f2b146105af578063e985e9c5146105cd578063f2fde38b146105f4575b005b34801561015e57600080fd5b50610174600160e060020a031960043516610615565b604080519115158252519081900360200190f35b34801561019457600080fd5b5061019d6107f5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101d75781810151838201526020016101bf565b50505050905090810190601f1680156102045780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561021e57600080fd5b5061022a60043561082c565b60408051600160a060020a039092168252519081900360200190f35b610150600160a060020a036004351660243561094f565b610150600160a060020a03600480358216916024803590911691604435918201910135610c67565b610150600160a060020a0360043581169060243516604435611097565b6101746004356113bb565b610150600160a060020a03600435811690602435166044356119d8565b3480156102d657600080fd5b506101506119f9565b3480156102eb57600080fd5b50610174600435611a4e565b34801561030357600080fd5b5061030f600435611bbe565b60405180898152602001888152602001878152602001868152602001858152602001848152602001836000191660001916815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561037e578181015183820152602001610366565b50505050905090810190601f1680156103ab5780820380516001836020036101000a031916815260200191505b50995050505050505050505060405180910390f35b3480156103cc57600080fd5b5061022a600435611dbc565b3480156103e457600080fd5b506103f9600160a060020a0360043516611e4d565b60408051918252519081900360200190f35b34801561041757600080fd5b50610150611ecc565b34801561042c57600080fd5b50610150611f54565b34801561044157600080fd5b50610150600160a060020a0360043516611f79565b34801561046257600080fd5b5061047660043560243560443515156120c8565b6040518080602001838152602001828103825284818151815260200191508051906020019060200280838360005b838110156104bc5781810151838201526020016104a4565b50505050905001935050505060405180910390f35b3480156104dd57600080fd5b5061022a612268565b3480156104f257600080fd5b5061019d612277565b34801561050757600080fd5b50610150600160a060020a036004351660243515156122ae565b34801561052d57600080fd5b506101746004356024351515612396565b610150600160a060020a03600480358216916024803590911691604435916064359081019101356126d1565b34801561057657600080fd5b5061015060043561270d565b34801561058e57600080fd5b5061019d60043561281f565b3480156105a657600080fd5b5061022a612b2f565b61017460048035906024803591604435918201910135606435612b3e565b3480156105d957600080fd5b50610174600160a060020a0360043581169060243516612f4f565b34801561060057600080fd5b50610150600160a060020a0360043516612fac565b600254604080517f5e0f9e060000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691635e0f9e0691600480830192602092919082900301818787803b15801561067457600080fd5b505af1158015610688573d6000803e3d6000fd5b505050506040513d602081101561069e57600080fd5b5051600160e060020a0319838116911614806107445750600260009054906101000a9004600160a060020a0316600160a060020a031663c1752ef16040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561070857600080fd5b505af115801561071c573d6000803e3d6000fd5b505050506040513d602081101561073257600080fd5b5051600160e060020a03198381169116145b806107d95750600260009054906101000a9004600160a060020a0316600160a060020a0316633f2e681c6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561079d57600080fd5b505af11580156107b1573d6000803e3d6000fd5b505050506040513d60208110156107c757600080fd5b5051600160e060020a03198381169116145b80156107ef5750600160e060020a031980831614155b92915050565b60408051808201909152601181527f54726970696f20526f6f6d204e69676874000000000000000000000000000000602082015290565b60008181811161083b57600080fd5b6002546040805160e060020a63e7f95c45028152600481018490529051600092600160a060020a03169163e7f95c4591602480830192602092919082900301818787803b15801561088b57600080fd5b505af115801561089f573d6000803e3d6000fd5b505050506040513d60208110156108b557600080fd5b5051600160a060020a031614156108cb57600080fd5b6002546040805160e160020a632376fe85028152600481018690529051600160a060020a03909216916346edfd0a916024808201926020929091908290030181600087803b15801561091c57600080fd5b505af1158015610930573d6000803e3d6000fd5b505050506040513d602081101561094657600080fd5b50519392505050565b60008181811161095e57600080fd5b6002546040805160e060020a63e7f95c45028152600481018490529051600092600160a060020a03169163e7f95c4591602480830192602092919082900301818787803b1580156109ae57600080fd5b505af11580156109c2573d6000803e3d6000fd5b505050506040513d60208110156109d857600080fd5b5051600160a060020a031614156109ee57600080fd5b6002546040805160e060020a63e7f95c45028152600481018690529051859260009283928392600160a060020a03169163e7f95c4591602480830192602092919082900301818787803b158015610a4457600080fd5b505af1158015610a58573d6000803e3d6000fd5b505050506040513d6020811015610a6e57600080fd5b50516002546040805160e260020a6303657815028152600160a060020a038085166004830181905233602484018190529351959850929092149550911691630d95e054916044808201926020929091908290030181600087803b158015610ad457600080fd5b505af1158015610ae8573d6000803e3d6000fd5b505050506040513d6020811015610afe57600080fd5b505190508180610b0b5750805b1515610b1657600080fd5b6002546040805160e060020a63e7f95c45028152600481018a90529051600160a060020a039092169163e7f95c45916024808201926020929091908290030181600087803b158015610b6757600080fd5b505af1158015610b7b573d6000803e3d6000fd5b505050506040513d6020811015610b9157600080fd5b5051600254604080517f6a385043000000000000000000000000000000000000000000000000000000008152600481018b9052600160a060020a038c811660248301529151939950911691636a3850439160448082019260009290919082900301818387803b158015610c0357600080fd5b505af1158015610c17573d6000803e3d6000fd5b5050604080518a81529051600160a060020a03808d1694508a1692507f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259181900360200190a35050505050505050565b6000808383808060200260200160405190810160405280939291908181526020018383602002808284375060009450505050505b8151811015610d775760008282815181101515610cb457fe5b6020908102909101015111610cc857600080fd5b6002548251600091600160a060020a03169063e7f95c4590859085908110610cec57fe5b906020019060200201516040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b158015610d2f57600080fd5b505af1158015610d43573d6000803e3d6000fd5b505050506040513d6020811015610d5957600080fd5b5051600160a060020a03161415610d6f57600080fd5b600101610c9b565b85858080602002602001604051908101604052809392919081815260200183836020028082843750600094508493508392508291508190505b8551851015610f9b576002548651600160a060020a039091169063e7f95c4590889088908110610ddc57fe5b906020019060200201516040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b158015610e1f57600080fd5b505af1158015610e33573d6000803e3d6000fd5b505050506040513d6020811015610e4957600080fd5b50516002548751919550600160a060020a038087163314955016906346edfd0a90889088908110610e7657fe5b906020019060200201516040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b158015610eb957600080fd5b505af1158015610ecd573d6000803e3d6000fd5b505050506040513d6020811015610ee357600080fd5b50516002546040805160e260020a6303657815028152600160a060020a038881166004830152336024830181905292519481169092149550911691630d95e054916044808201926020929091908290030181600087803b158015610f4657600080fd5b505af1158015610f5a573d6000803e3d6000fd5b505050506040513d6020811015610f7057600080fd5b505190508280610f7d5750815b80610f855750805b1515610f9057600080fd5b600190940193610db0565b600099505b8a8a101561108757600254600160a060020a031663e7f95c458d8d8d818110610fc557fe5b905060200201356040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561100557600080fd5b505af1158015611019573d6000803e3d6000fd5b505050506040513d602081101561102f57600080fd5b50519850600160a060020a03808a16908f161461104b57600080fd5b600160a060020a038d16151561106057600080fd5b61107c8c8c8c81811061106f57fe5b905060200201358e612ff2565b600190990198610fa0565b5050505050505050505050505050565b6000818181116110a657600080fd5b6002546040805160e060020a63e7f95c45028152600481018490529051600092600160a060020a03169163e7f95c4591602480830192602092919082900301818787803b1580156110f657600080fd5b505af115801561110a573d6000803e3d6000fd5b505050506040513d602081101561112057600080fd5b5051600160a060020a0316141561113657600080fd5b82600080600080600260009054906101000a9004600160a060020a0316600160a060020a031663e7f95c45866040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561119b57600080fd5b505af11580156111af573d6000803e3d6000fd5b505050506040513d60208110156111c557600080fd5b50516002546040805160e160020a632376fe85028152600481018990529051929650600160a060020a0380881633149650909116916346edfd0a916024808201926020929091908290030181600087803b15801561122257600080fd5b505af1158015611236573d6000803e3d6000fd5b505050506040513d602081101561124c57600080fd5b50516002546040805160e260020a6303657815028152600160a060020a038881166004830152336024830181905292519481169092149550911691630d95e054916044808201926020929091908290030181600087803b1580156112af57600080fd5b505af11580156112c3573d6000803e3d6000fd5b505050506040513d60208110156112d957600080fd5b5051905082806112e65750815b806112ee5750805b15156112f957600080fd5b6002546040805160e060020a63e7f95c45028152600481018b90529051600160a060020a039092169163e7f95c45916024808201926020929091908290030181600087803b15801561134a57600080fd5b505af115801561135e573d6000803e3d6000fd5b505050506040513d602081101561137457600080fd5b50519650600160a060020a03808816908b161461139057600080fd5b600160a060020a03891615156113a557600080fd5b6113af888a612ff2565b50505050505050505050565b60008080808080808080808a8181116113d357600080fd5b6002546040805160e060020a63e7f95c45028152600481018490529051600092600160a060020a03169163e7f95c4591602480830192602092919082900301818787803b15801561142357600080fd5b505af1158015611437573d6000803e3d6000fd5b505050506040513d602081101561144d57600080fd5b5051600160a060020a0316141561146357600080fd5b6002546040805160e060020a63e7f95c45028152600481018f90529051600160a060020a03909216916330c7090391839163e7f95c45916024808201926020929091908290030181600087803b1580156114bc57600080fd5b505af11580156114d0573d6000803e3d6000fd5b505050506040513d60208110156114e657600080fd5b81019080805190602001909291905050508e6040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050602060405180830381600087803b15801561154a57600080fd5b505af115801561155e573d6000803e3d6000fd5b505050506040513d602081101561157457600080fd5b5051151561158157600080fd5b600254604080517f3bdf5878000000000000000000000000000000000000000000000000000000008152600481018f90529051600160a060020a0390921691633bdf58789160248082019260e0929091908290030181600087803b1580156115e857600080fd5b505af11580156115fc573d6000803e3d6000fd5b505050506040513d60e081101561161257600080fd5b8101908080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190505050509a50509950995099509950600260009054906101000a9004600160a060020a0316600160a060020a03166365de1eb38b6040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b1580156116c957600080fd5b505af11580156116dd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052608081101561170657600080fd5b81019080805164010000000081111561171e57600080fd5b8201602081018481111561173157600080fd5b815164010000000081118282018710171561174b57600080fd5b5050506020015196505050600160a060020a038516331461176b57600080fd5b6002546040805160e060020a63e7f95c45028152600481018f90529051600160a060020a039092169163e7f95c45916024808201926020929091908290030181600087803b1580156117bc57600080fd5b505af11580156117d0573d6000803e3d6000fd5b505050506040513d60208110156117e657600080fd5b5051935087151561183d578692503483111561180157600080fd5b604051600160a060020a0385169084156108fc029085906000818181858888f19350505050158015611837573d6000803e3d6000fd5b5061197f565b6000871161184a57600080fd5b600254604080517fa306cdeb000000000000000000000000000000000000000000000000000000008152600481018b90529051600160a060020a039092169163a306cdeb916024808201926020929091908290030181600087803b1580156118b157600080fd5b505af11580156118c5573d6000803e3d6000fd5b505050506040513d60208110156118db57600080fd5b5051604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152600160a060020a038781166024830152604482018b90529151929450908416916323b872dd916064808201926020929091908290030181600087803b15801561195257600080fd5b505af1158015611966573d6000803e3d6000fd5b505050506040513d602081101561197c57600080fd5b50505b61198b8c8b8b89613153565b60408051338152602081018e905281517fbb28353e4598c3b9199101a66e0989549b659a59a54d2c27fbb183f1932c8e6d929181900390910190a15060019b9a5050505050505050505050565b6119f483838360206040519081016040528060008152506132f2565b505050565b600054600160a060020a03163314611a1057600080fd5b60008054604051600160a060020a0390911691303180156108fc02929091818181858888f19350505050158015611a4b573d6000803e3d6000fd5b50565b600081818111611a5d57600080fd5b6002546040805160e060020a63e7f95c45028152600481018490529051600092600160a060020a03169163e7f95c4591602480830192602092919082900301818787803b158015611aad57600080fd5b505af1158015611ac1573d6000803e3d6000fd5b505050506040513d6020811015611ad757600080fd5b5051600160a060020a03161415611aed57600080fd5b6002546040805160e060020a63e7f95c45028152600481018690529051600160a060020a03909216916330c7090391839163e7f95c45916024808201926020929091908290030181600087803b158015611b4657600080fd5b505af1158015611b5a573d6000803e3d6000fd5b505050506040513d6020811015611b7057600080fd5b50516040805160e060020a63ffffffff8516028152600160a060020a039092166004830152602482018790525160448083019260209291908290030181600087803b15801561091c57600080fd5b60008060008060008060006060600260009054906101000a9004600160a060020a0316600160a060020a0316633bdf58788a6040518263ffffffff1660e060020a0281526004018082815260200191505060e060405180830381600087803b158015611c2957600080fd5b505af1158015611c3d573d6000803e3d6000fd5b505050506040513d60e0811015611c5357600080fd5b8101908080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190505050809850819950829a50839b50849c50859d50869e5050505050505050600260009054906101000a9004600160a060020a0316600160a060020a031663762fdc0c89896040518363ffffffff1660e060020a0281526004018083815260200182815260200192505050600060405180830381600087803b158015611d2257600080fd5b505af1158015611d36573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526060811015611d5f57600080fd5b810190808051640100000000811115611d7757600080fd5b82016020810184811115611d8a57600080fd5b8151640100000000811182820187101715611da457600080fd5b509b9d9a9c50989a5096989597949650929492505050565b6000808211611dca57600080fd5b6002546040805160e060020a63e7f95c45028152600481018590529051600160a060020a039092169163e7f95c45916024808201926020929091908290030181600087803b158015611e1b57600080fd5b505af1158015611e2f573d6000803e3d6000fd5b505050506040513d6020811015611e4557600080fd5b505192915050565b6000600160a060020a0382161515611e6457600080fd5b600254604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a038581166004830152915191909216916370a082319160248083019260209291908290030181600087803b158015611e1b57600080fd5b600154600160a060020a03163314611ee357600080fd5b60015460008054604051600160a060020a0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600180546000805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155169055565b600054600160a060020a03163314611f6b57600080fd5b600054600160a060020a0316ff5b600080548190600160a060020a03163314611f9357600080fd5b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051849350600160a060020a038416916370a082319160248083019260209291908290030181600087803b158015611ff757600080fd5b505af115801561200b573d6000803e3d6000fd5b505050506040513d602081101561202157600080fd5b505160008054604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0392831660048201526024810185905290519394509085169263a9059cbb92604480840193602093929083900390910190829087803b15801561209757600080fd5b505af11580156120ab573d6000803e3d6000fd5b505050506040513d60208110156120c157600080fd5b5050505050565b6060600082156121e657600254604080517f4cb0c7a10000000000000000000000000000000000000000000000000000000081523360048201526024810188905260448101879052600160648201529051600160a060020a0390921691634cb0c7a19160848082019260009290919082900301818387803b15801561214c57600080fd5b505af1158015612160573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604090815281101561218957600080fd5b8101908080516401000000008111156121a157600080fd5b820160208101848111156121b457600080fd5b81518560208202830111640100000000821117156121d157600080fd5b50506020909101519094509250612260915050565b600254604080517f600cf0d90000000000000000000000000000000000000000000000000000000081523360048201526024810188905260448101879052600160648201529051600160a060020a039092169163600cf0d99160848082019260009290919082900301818387803b15801561214c57600080fd5b935093915050565b600054600160a060020a031681565b60408051808201909152600381527f54524e0000000000000000000000000000000000000000000000000000000000602082015290565b600160a060020a03821615156122c357600080fd5b600254604080517f35058a2a000000000000000000000000000000000000000000000000000000008152600160a060020a0385811660048301523360248301528415156044830152915191909216916335058a2a91606480830192600092919082900301818387803b15801561233857600080fd5b505af115801561234c573d6000803e3d6000fd5b50506040805184151581529051600160a060020a03861693503392507f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319181900360200190a35050565b6000828181116123a557600080fd5b6002546040805160e060020a63e7f95c45028152600481018490529051600092600160a060020a03169163e7f95c4591602480830192602092919082900301818787803b1580156123f557600080fd5b505af1158015612409573d6000803e3d6000fd5b505050506040513d602081101561241f57600080fd5b5051600160a060020a0316141561243557600080fd5b83600080600080600260009054906101000a9004600160a060020a0316600160a060020a031663e7f95c45866040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561249a57600080fd5b505af11580156124ae573d6000803e3d6000fd5b505050506040513d60208110156124c457600080fd5b50516002546040805160e160020a632376fe85028152600481018990529051929650600160a060020a0380881633149650909116916346edfd0a916024808201926020929091908290030181600087803b15801561252157600080fd5b505af1158015612535573d6000803e3d6000fd5b505050506040513d602081101561254b57600080fd5b50516002546040805160e260020a6303657815028152600160a060020a038881166004830152336024830181905292519481169092149550911691630d95e054916044808201926020929091908290030181600087803b1580156125ae57600080fd5b505af11580156125c2573d6000803e3d6000fd5b505050506040513d60208110156125d857600080fd5b5051905082806125e55750815b806125ed5750805b15156125f857600080fd5b600254604080517f602b7001000000000000000000000000000000000000000000000000000000008152336004820152602481018c90528a151560448201529051600160a060020a039092169163602b70019160648082019260009290919082900301818387803b15801561266c57600080fd5b505af1158015612680573d6000803e3d6000fd5b5050604080513381528b1515602082015281518d94507fa8b03d10e96b23d3ed7630fcc9e32aec81ef79975e8d1345dd9e98306b73805393509081900390910190a250600198975050505050505050565b6120c185858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437506132f2945050505050565b600080548190600160a060020a0316331461272757600080fd5b600254604080517fa306cdeb000000000000000000000000000000000000000000000000000000008152600481018690529051600160a060020a039092169163a306cdeb916024808201926020929091908290030181600087803b15801561278e57600080fd5b505af11580156127a2573d6000803e3d6000fd5b505050506040513d60208110156127b857600080fd5b5051604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051919350600160a060020a038416916370a08231916024808201926020929091908290030181600087803b158015611ff757600080fd5b60608060008180808684811161283457600080fd5b6002546040805160e060020a63e7f95c45028152600481018490529051600092600160a060020a03169163e7f95c4591602480830192602092919082900301818787803b15801561288457600080fd5b505af1158015612898573d6000803e3d6000fd5b505050506040513d60208110156128ae57600080fd5b5051600160a060020a031614156128c457600080fd5b60408051600280825281830183529091602083019080388339505081519197507f120000000000000000000000000000000000000000000000000000000000000091889150600090811061291457fe5b906020010190600160f860020a031916908160001a90535085517f2000000000000000000000000000000000000000000000000000000000000000908790600190811061295d57fe5b906020010190600160f860020a031916908160001a905350600254604080517f3bdf5878000000000000000000000000000000000000000000000000000000008152600481018b90529051600160a060020a0390921691633bdf58789160248082019260e0929091908290030181600087803b1580156129dc57600080fd5b505af11580156129f0573d6000803e3d6000fd5b505050506040513d60e0811015612a0657600080fd5b5060c001519450612a26612a19866137cb565b879063ffffffff61385116565b9350612a3184613966565b9250600260009054906101000a9004600160a060020a0316600160a060020a0316634e99b8006040518163ffffffff1660e060020a028152600401600060405180830381600087803b158015612a8657600080fd5b505af1158015612a9a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612ac357600080fd5b810190808051640100000000811115612adb57600080fd5b82016020810184811115612aee57600080fd5b8151640100000000811182820187101715612b0857600080fd5b50909550612b2393508592508691505063ffffffff61385116565b98975050505050505050565b600154600160a060020a031681565b600080600087876000600260009054906101000a9004600160a060020a0316600160a060020a03166365de1eb3846040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b158015612ba557600080fd5b505af1158015612bb9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526080811015612be257600080fd5b810190808051640100000000811115612bfa57600080fd5b82016020810184811115612c0d57600080fd5b8151640100000000811182820187101715612c2757600080fd5b5050506060015192505050801515612c3e57600080fd5b600254604080517f6b65a83400000000000000000000000000000000000000000000000000000000815260048101869052602481018590529051600160a060020a0390921691636b65a834916044808201926020929091908290030181600087803b158015612cac57600080fd5b505af1158015612cc0573d6000803e3d6000fd5b505050506040513d6020811015612cd657600080fd5b50511515612ce357600080fd5b8888808060200260200160405190810160405280939291908181526020018383602002808284375060009450505050505b8151811015612d745760008282815181101515612d2d57fe5b6020908102909101015111612d4157600080fd5b612d618282815181101515612d5257fe5b90602001906020020151613aed565b1515612d6c57600080fd5b600101612d14565b600260009054906101000a9004600160a060020a0316600160a060020a03166365de1eb38e6040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b158015612dd257600080fd5b505af1158015612de6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526080811015612e0f57600080fd5b810190808051640100000000811115612e2757600080fd5b82016020810184811115612e3a57600080fd5b8151640100000000811182820187101715612e5457600080fd5b50509291906020018051906020019092919080519060200190929190805190602001909291905050505050975050612ebe8d888e8e8e808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050508d613bf8565b9550851515612ecc57600080fd5b8b87600160a060020a031633600160a060020a03167f378b913ef532468f5ca14ee9e03c0b47e22440edd666fd7fcb4b7f146c1b752a8e8e8e604051808060200183815260200182810382528585828181526020019250602002808284376040519201829003965090945050505050a45060019c9b505050505050505050505050565b6002546040805160e260020a6303657815028152600160a060020a038581166004830152848116602483015291516000939290921691630d95e0549160448082019260209290919082900301818787803b15801561091c57600080fd5b600054600160a060020a03163314612fc357600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6002546040805160e060020a63e7f95c45028152600481018590529051600092600160a060020a03169163e7f95c4591602480830192602092919082900301818787803b15801561304257600080fd5b505af1158015613056573d6000803e3d6000fd5b505050506040513d602081101561306c57600080fd5b5051905061307a8184613fea565b61308682846000614074565b600254604080517f491a790400000000000000000000000000000000000000000000000000000000815260048101869052600160a060020a0385811660248301529151919092169163491a790491604480830192600092919082900301818387803b1580156130f457600080fd5b505af1158015613108573d6000803e3d6000fd5b5050604080518681529051600160a060020a038087169450851692507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b6002546040805160e060020a63e7f95c450281526004810187905290516131d792600160a060020a03169163e7f95c459160248083019260209291908290030181600087803b1580156131a557600080fd5b505af11580156131b9573d6000803e3d6000fd5b505050506040513d60208110156131cf57600080fd5b505185613fea565b600254604080517fbbb7eb64000000000000000000000000000000000000000000000000000000008152600481018690526024810185905260448101849052600160648201529051600160a060020a039092169163bbb7eb649160848082019260009290919082900301818387803b15801561325257600080fd5b505af1158015613266573d6000803e3d6000fd5b5050600254604080517f491a7904000000000000000000000000000000000000000000000000000000008152600481018990526000602482018190529151600160a060020a03909316945063491a790493506044808201939182900301818387803b1580156132d457600080fd5b505af11580156132e8573d6000803e3d6000fd5b5050505050505050565b600080808481811161330357600080fd5b6002546040805160e060020a63e7f95c45028152600481018490529051600092600160a060020a03169163e7f95c4591602480830192602092919082900301818787803b15801561335357600080fd5b505af1158015613367573d6000803e3d6000fd5b505050506040513d602081101561337d57600080fd5b5051600160a060020a0316141561339357600080fd5b85600080600080600260009054906101000a9004600160a060020a0316600160a060020a031663e7f95c45866040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b1580156133f857600080fd5b505af115801561340c573d6000803e3d6000fd5b505050506040513d602081101561342257600080fd5b50516002546040805160e160020a632376fe85028152600481018990529051929650600160a060020a0380881633149650909116916346edfd0a916024808201926020929091908290030181600087803b15801561347f57600080fd5b505af1158015613493573d6000803e3d6000fd5b505050506040513d60208110156134a957600080fd5b50516002546040805160e260020a6303657815028152600160a060020a038881166004830152336024830181905292519481169092149550911691630d95e054916044808201926020929091908290030181600087803b15801561350c57600080fd5b505af1158015613520573d6000803e3d6000fd5b505050506040513d602081101561353657600080fd5b5051905082806135435750815b8061354b5750805b151561355657600080fd5b6002546040805160e060020a63e7f95c45028152600481018e90529051600160a060020a039092169163e7f95c45916024808201926020929091908290030181600087803b1580156135a757600080fd5b505af11580156135bb573d6000803e3d6000fd5b505050506040513d60208110156135d157600080fd5b50519850600160a060020a03808a16908e16146135ed57600080fd5b600160a060020a038c16151561360257600080fd5b61360c8b8d612ff2565b8b3b975087151561361c576137bc565b8b600160a060020a031663f0b9e5ba8e8d8d6040518463ffffffff1660e060020a0281526004018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561369b578181015183820152602001613683565b50505050905090810190601f1680156136c85780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156136e957600080fd5b505af11580156136fd573d6000803e3d6000fd5b505050506040513d602081101561371357600080fd5b5051600254604080517fecc98ce40000000000000000000000000000000000000000000000000000000081529051929950600160a060020a039091169163ecc98ce4916004808201926020929091908290030181600087803b15801561377857600080fd5b505af115801561378c573d6000803e3d6000fd5b505050506040513d60208110156137a257600080fd5b5051600160e060020a03198881169116146137bc57600080fd5b50505050505050505050505050565b604080516020808252818301909252606091829160009180820161040080388339019050509150600090505b60208160ff16101561384a578360ff82166020811061381257fe5b1a60f860020a02828260ff1681518110151561382a57fe5b906020010190600160f860020a031916908160001a9053506001016137f7565b5092915050565b606080600083518551016040519080825280601f01601f191660200182016040528015613888578160200160208202803883390190505b509150600090505b84518161ffff1610156138f457848161ffff168151811015156138af57fe5b90602001015160f860020a900460f860020a02828261ffff168151811015156138d457fe5b906020010190600160f860020a031916908160001a905350600101613890565b83518551018161ffff16101561395e578385518261ffff160381518110151561391957fe5b90602001015160f860020a900460f860020a02828261ffff1681518110151561393e57fe5b906020010190600160f860020a031916908160001a9053506001016138f4565b509392505050565b6060806000806000806064875160880281151561397f57fe5b046001016040519080825280602002602001820160405280156139ac578160200160208202803883390190505b50945060008560008151811015156139c057fe5b60ff90921660209283029091019091015260019350600092505b8651831015613ac85786838151811015156139f157fe5b90602001015160f860020a900460f860020a0260f860020a900460ff169150600090505b8360ff16811015613a7d578481815181101515613a2e57fe5b9060200190602002015160ff166101000282019150603a82811515613a4f57fe5b068582815181101515613a5e57fe5b60ff909216602092830290910190910152603a82049150600101613a15565b6000821115613abd57603a8206858560ff16815181101515613a9b57fe5b60ff909216602092830290910190910152600190930192603a82049150613a7d565b8260010192506139da565b613ae2613add613ad887876141bb565b61423f565b6142c5565b979650505050505050565b6000612710808304906064808302818604039183029082028503036107b2831080613b19575060008211155b80613b245750600c82115b80613b30575060008111155b80613b3b5750601f81115b15613b495760009350613bf0565b8160041480613b585750816006145b80613b635750816009145b80613b6e575081600b145b15613b855780601f1415613b855760009350613bf0565b60048306158015613b9857506064830615155b80613ba557506101908306155b15613bcd57816002148015613bba5750601d81115b15613bc85760009350613bf0565b613beb565b816002148015613bdd5750601c81115b15613beb5760009350613bf0565b600193505b505050919050565b6000606080600080600080600260009054906101000a9004600160a060020a0316600160a060020a031663644e8b248d8c8c8c6040518563ffffffff1660e060020a0281526004018085815260200184815260200180602001838152602001828103825284818151815260200191508051906020019060200280838360005b83811015613c8f578181015183820152602001613c77565b5050505090500195505050505050600060405180830381600087803b158015613cb757600080fd5b505af1158015613ccb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040908152811015613cf457600080fd5b810190808051640100000000811115613d0c57600080fd5b82016020810184811115613d1f57600080fd5b8151856020820283011164010000000082111715613d3c57600080fd5b50509291906020018051640100000000811115613d5857600080fd5b82016020810184811115613d6b57600080fd5b8151856020820283011164010000000082111715613d8857600080fd5b50949a50985060009750879650505050505b8851831015613e3d578583815181101515613db157fe5b9060200190602002015161ffff1660001480613de457508483815181101515613dd657fe5b906020019060200201516000145b15613df25760009650613fdb565b8483815181101515613e0057fe5b9060200190602002015184019350613e328c8b8b86815181101515613e2157fe5b90602001906020020151338c6143cf565b600190920191613d9a565b871515613e8c57348414613e5057600080fd5b604051600160a060020a038c169085156108fc029086906000818181858888f19350505050158015613e86573d6000803e3d6000fd5b50613fd6565b600254604080517fa306cdeb000000000000000000000000000000000000000000000000000000008152600481018b90529051600160a060020a039092169163a306cdeb916024808201926020929091908290030181600087803b158015613ef357600080fd5b505af1158015613f07573d6000803e3d6000fd5b505050506040513d6020811015613f1d57600080fd5b50519150600160a060020a0382161515613f3657600080fd5b50604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152600160a060020a038c8116602483015260448201869052915183928316916323b872dd9160648083019260209291908290030181600087803b158015613fa957600080fd5b505af1158015613fbd573d6000803e3d6000fd5b505050506040513d6020811015613fd357600080fd5b50505b600196505b50505050505095945050505050565b600254604080517f28543417000000000000000000000000000000000000000000000000000000008152600160a060020a0385811660048301526024820185905291519190921691632854341791604480830192600092919082900301818387803b15801561405857600080fd5b505af115801561406c573d6000803e3d6000fd5b505050505050565b600160a060020a038316151561408957600080fd5b81151561409557600080fd5b801561412b57600254604080517f6cd44d55000000000000000000000000000000000000000000000000000000008152600160a060020a038681166004830152602482018690526000604483018190529251931692636cd44d559260648084019391929182900301818387803b15801561410e57600080fd5b505af1158015614122573d6000803e3d6000fd5b505050506119f4565b600254604080517f5ec5bc8e000000000000000000000000000000000000000000000000000000008152600160a060020a038681166004830152602482018690526000604483018190529251931692635ec5bc8e9260648084019391929182900301818387803b15801561419e57600080fd5b505af11580156141b2573d6000803e3d6000fd5b50505050505050565b60608060008360ff166040519080825280602002602001820160405280156141ed578160200160208202803883390190505b509150600090505b8360ff1681101561395e57848181518110151561420e57fe5b90602001906020020151828281518110151561422657fe5b60ff9092166020928302909101909101526001016141f5565b6060806000835160405190808252806020026020018201604052801561426f578160200160208202803883390190505b509150600090505b835181101561384a57835184908281036000190190811061429457fe5b9060200190602002015182828151811015156142ac57fe5b60ff909216602092830290910190910152600101614277565b606080600083516040519080825280601f01601f1916602001820160405280156142f9578160200160208202803883390190505b509150600090505b835181101561384a57606060405190810160405280603a81526020017f31323334353637383941424344454647484a4b4c4d4e5051525354555657585981526020017f5a6162636465666768696a6b6d6e6f707172737475767778797a000000000000815250848281518110151561437557fe5b9060200190602002015160ff1681518110151561438e57fe5b90602001015160f860020a900460f860020a0282828151811015156143af57fe5b906020010190600160f860020a031916908160001a905350600101614301565b600254604080517fc4725577000000000000000000000000000000000000000000000000000000008152600481018890526024810187905260448101869052606481018490529051600092839283928392600160a060020a03169163c472557791608480830192606092919082900301818787803b15801561445057600080fd5b505af1158015614464573d6000803e3d6000fd5b505050506040513d606081101561447a57600080fd5b5060409081015160025482517f762fdc0c000000000000000000000000000000000000000000000000000000008152600481018d9052602481018c90529251919650600160a060020a03169163762fdc0c91604480830192600092919082900301818387803b1580156144ec57600080fd5b505af1158015614500573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052606081101561452957600080fd5b81019080805164010000000081111561454157600080fd5b8201602081018481111561455457600080fd5b815164010000000081118282018710171561456e57600080fd5b50505060409081015160025482517fc6f70370000000000000000000000000000000000000000000000000000000008152600481018f9052602481018e9052604481018d9052606481018b9052608481018a905260a481018390529251919750600160a060020a0316935063c6f70370925060c48083019260209291908290030181600087803b15801561460157600080fd5b505af1158015614615573d6000803e3d6000fd5b505050506040513d602081101561462b57600080fd5b5051600254604080517f491a790400000000000000000000000000000000000000000000000000000000815260048101849052600160a060020a038a81166024830152915193955091169163491a79049160448082019260009290919082900301818387803b15801561469d57600080fd5b505af11580156146b1573d6000803e3d6000fd5b505050506146c186836000614074565b600254604080517f65de1eb3000000000000000000000000000000000000000000000000000000008152600481018c90529051600160a060020a03909216916365de1eb39160248082019260009290919082900301818387803b15801561472757600080fd5b505af115801561473b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052608081101561476457600080fd5b81019080805164010000000081111561477c57600080fd5b8201602081018481111561478f57600080fd5b81516401000000008111828201871017156147a957600080fd5b5050506020015192506147c29150829050836001614074565b600254604080517fde5dead6000000000000000000000000000000000000000000000000000000008152600481018c9052602481018b9052604481018a9052600160648201529051600160a060020a039092169163de5dead69160848082019260009290919082900301818387803b15801561483d57600080fd5b505af11580156137bc573d6000803e3d6000fd00a165627a7a72305820158c88fdb7d1763655f4899299cf7bd51ca84e2a69500481dd9276c31595f5700029000000000000000000000000829bcf8c990bd4c0de2a32a3a21068e0d154705d

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

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000829bcf8c990bd4c0de2a32a3a21068e0d154705d


   Swarm Source:
bzzr://158c88fdb7d1763655f4899299cf7bd51ca84e2a69500481dd9276c31595f570

 

View All
Block Age transaction Difficulty GasUsed Reward
View All
Block Age UncleNumber Difficulty GasUsed Reward