More Info
Private Name Tags
Latest 25 from a total of 1,431 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Claim Rent | 20244463 | 3 days ago | IN | 0 ETH | 0.00015956 | ||||
Stop Lend | 20042166 | 32 days ago | IN | 0 ETH | 0.0011082 | ||||
Lend | 19953638 | 44 days ago | IN | 0 ETH | 0.00035298 | ||||
Lend | 19902597 | 51 days ago | IN | 0 ETH | 0.00041998 | ||||
Rent | 19801458 | 65 days ago | IN | 0 ETH | 0.00057821 | ||||
Lend | 19749897 | 73 days ago | IN | 0 ETH | 0.00043647 | ||||
Lend | 19646759 | 87 days ago | IN | 0 ETH | 0.00172507 | ||||
Stop Lend | 19340849 | 130 days ago | IN | 0 ETH | 0.00502438 | ||||
Claim Rent | 19340667 | 130 days ago | IN | 0 ETH | 0.00422311 | ||||
Stop Lend | 19301502 | 135 days ago | IN | 0 ETH | 0.00211902 | ||||
Lend | 19292287 | 137 days ago | IN | 0 ETH | 0.002961 | ||||
Lend | 19186127 | 152 days ago | IN | 0 ETH | 0.00844108 | ||||
Stop Lend | 19164265 | 155 days ago | IN | 0 ETH | 0.00145752 | ||||
Lend | 19163548 | 155 days ago | IN | 0 ETH | 0.00239742 | ||||
Stop Lend | 19074536 | 167 days ago | IN | 0 ETH | 0.00069767 | ||||
Claim Rent | 19074513 | 167 days ago | IN | 0 ETH | 0.00085005 | ||||
Lend | 19070512 | 168 days ago | IN | 0 ETH | 0.00217466 | ||||
Stop Lend | 19036069 | 173 days ago | IN | 0 ETH | 0.00230844 | ||||
Rent | 19019576 | 175 days ago | IN | 0 ETH | 0.00265158 | ||||
Rent | 18957022 | 184 days ago | IN | 0 ETH | 0.00320531 | ||||
Stop Lend | 18948052 | 185 days ago | IN | 0 ETH | 0.00090629 | ||||
Claim Rent | 18948049 | 185 days ago | IN | 0 ETH | 0.00152418 | ||||
Rent | 18946471 | 185 days ago | IN | 0 ETH | 0.00110517 | ||||
Stop Lend | 18942272 | 186 days ago | IN | 0 ETH | 0.00258938 | ||||
Stop Lend | 18941186 | 186 days ago | IN | 0 ETH | 0.00132132 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
Registry
Compiler Version
v0.8.7+commit.e28d00a7
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-09-10 */ // SPDX-License-Identifier: MIT pragma solidity 0.8.7; // Part: IRegistry // @@@@@@@@@@@@@@@@ ,@@@@@@@@@@@@@@@@ // @@@,,,,,,,,,,@@@ ,@@&,,,,,,,,,,@@@ // @@@@@@@@,,,,,,,,,,@@@@@@@@& ,@@&,,,,,,,,,,@@@@@@@@ // @@@**********@@@@@@@@@@@@@& ,@@@@@@@@**********@@@ // @@@**********@@@@@@@@@@@@@& ,@@@@@@@@**********@@@@@@@@ // @@@**********@@@@@@@@@@@@@& .@@@**********@@@@@@@@ // @@@@@@@@**********@@@@@@@@@@@@@& .@@@**********@@@@@@@@ // @@@**********@@@@@@@@@@@@@& .@@@@@@@@**********@@@ // @@@**********@@@@@@@@@@@@@& .@@@@@@@@**********@@@@@@@@ // @@@@@@@@**********@@@@@@@@& .@@@**********@@@@@@@@@@@@@ // @@@@@@@@//////////@@@@@@@@& .@@@//////////@@@@@@@@@@@@@ // @@@//////////@@@@@@@@& .@@@//////////@@@@@@@@@@@@@ // @@@//////////@@@@@@@@& ,@@@@@@@@//////////@@@@@@@@@@@@@ // @@@%%%%%/////(((((@@@& ,@@@(((((/////%%%%%@@@@@@@@ // @@@@@@@@//////////@@@@@@@@& ,@@@//////////@@@@@@@@@@@@@ // @@@%%%%%%%%%%@@@@@@@@& ,@@@%%%%%%%%%%@@@@@@@@@@@@@ // @@@@@@@@@@@@@@@@@@@@@& ,@@@@@@@@@@@@@@@@@@@@@@@@@@ // @@@@@@@@@@@@@@@@& @@@@@@@@@@@@@@@@ // @@@@@@@@@@@@@@@@& @@@@@@@@@@@@@@@@ interface IRegistry { event Lend( bool is721, address indexed lenderAddress, address indexed nftAddress, uint256 indexed tokenID, uint256 lendingID, uint8 maxRentDuration, bytes4 dailyRentPrice, uint16 lendAmount, IResolver.PaymentToken paymentToken ); event Rent( address indexed renterAddress, uint256 indexed lendingID, uint256 indexed rentingID, uint16 rentAmount, uint8 rentDuration, uint32 rentedAt ); event StopLend(uint256 indexed lendingID, uint32 stoppedAt); event StopRent(uint256 indexed rentingID, uint32 stoppedAt); event RentClaimed(uint256 indexed rentingID, uint32 collectedAt); enum NFTStandard { E721, E1155 } struct CallData { uint256 left; uint256 right; IRegistry.NFTStandard[] nftStandard; address[] nftAddress; uint256[] tokenID; uint256[] lendAmount; uint8[] maxRentDuration; bytes4[] dailyRentPrice; uint256[] lendingID; uint256[] rentingID; uint8[] rentDuration; uint256[] rentAmount; IResolver.PaymentToken[] paymentToken; } // 2, 162, 170, 202, 218, 234, 242 struct Lending { NFTStandard nftStandard; address payable lenderAddress; uint8 maxRentDuration; bytes4 dailyRentPrice; uint16 lendAmount; uint16 availableAmount; IResolver.PaymentToken paymentToken; } // 180, 212 struct Renting { address payable renterAddress; uint8 rentDuration; uint32 rentedAt; uint16 rentAmount; } // creates the lending structs and adds them to the enumerable set function lend( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory lendAmount, uint8[] memory maxRentDuration, bytes4[] memory dailyRentPrice, IResolver.PaymentToken[] memory paymentToken ) external; function stopLend( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory lendingID ) external; // // creates the renting structs and adds them to the enumerable set function rent( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory lendingID, uint8[] memory rentDuration, uint256[] memory rentAmount ) external payable; function stopRent( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory lendingID, uint256[] memory rentingID ) external; function claimRent( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory lendingID, uint256[] memory rentingID ) external; } // Part: IResolver // @@@@@@@@@@@@@@@@ ,@@@@@@@@@@@@@@@@ // @@@,,,,,,,,,,@@@ ,@@&,,,,,,,,,,@@@ // @@@@@@@@,,,,,,,,,,@@@@@@@@& ,@@&,,,,,,,,,,@@@@@@@@ // @@@**********@@@@@@@@@@@@@& ,@@@@@@@@**********@@@ // @@@**********@@@@@@@@@@@@@& ,@@@@@@@@**********@@@@@@@@ // @@@**********@@@@@@@@@@@@@& .@@@**********@@@@@@@@ // @@@@@@@@**********@@@@@@@@@@@@@& .@@@**********@@@@@@@@ // @@@**********@@@@@@@@@@@@@& .@@@@@@@@**********@@@ // @@@**********@@@@@@@@@@@@@& .@@@@@@@@**********@@@@@@@@ // @@@@@@@@**********@@@@@@@@& .@@@**********@@@@@@@@@@@@@ // @@@@@@@@//////////@@@@@@@@& .@@@//////////@@@@@@@@@@@@@ // @@@//////////@@@@@@@@& .@@@//////////@@@@@@@@@@@@@ // @@@//////////@@@@@@@@& ,@@@@@@@@//////////@@@@@@@@@@@@@ // @@@%%%%%/////(((((@@@& ,@@@(((((/////%%%%%@@@@@@@@ // @@@@@@@@//////////@@@@@@@@& ,@@@//////////@@@@@@@@@@@@@ // @@@%%%%%%%%%%@@@@@@@@& ,@@@%%%%%%%%%%@@@@@@@@@@@@@ // @@@@@@@@@@@@@@@@@@@@@& ,@@@@@@@@@@@@@@@@@@@@@@@@@@ // @@@@@@@@@@@@@@@@& @@@@@@@@@@@@@@@@ // @@@@@@@@@@@@@@@@& @@@@@@@@@@@@@@@@ interface IResolver { enum PaymentToken { SENTINEL, DAI, USDC, TUSD } function getPaymentToken(uint8 _pt) external view returns (address); function setPaymentToken(uint8 _pt, address _v) external; } // Part: OpenZeppelin/[email protected]/Address /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // Part: OpenZeppelin/[email protected]/Context /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // Part: OpenZeppelin/[email protected]/IERC165 /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // Part: OpenZeppelin/[email protected]/IERC20 /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // Part: OpenZeppelin/[email protected]/IERC721Receiver /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } // Part: OpenZeppelin/[email protected]/ERC165 /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // Part: OpenZeppelin/[email protected]/ERC721Holder /** * @dev Implementation of the {IERC721Receiver} interface. * * Accepts all token transfers. * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}. */ contract ERC721Holder is IERC721Receiver { /** * @dev See {IERC721Receiver-onERC721Received}. * * Always returns `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address, address, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC721Received.selector; } } // Part: OpenZeppelin/[email protected]/IERC1155 /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; } // Part: OpenZeppelin/[email protected]/IERC1155Receiver /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** @dev Handles the receipt of a single ERC1155 token type. This function is called at the end of a `safeTransferFrom` after the balance has been updated. To accept the transfer, this must return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` (i.e. 0xf23a6e61, or its own function selector). @param operator The address which initiated the transfer (i.e. msg.sender) @param from The address which previously owned the token @param id The ID of the token being transferred @param value The amount of tokens being transferred @param data Additional data with no specified format @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** @dev Handles the receipt of a multiple ERC1155 token types. This function is called at the end of a `safeBatchTransferFrom` after the balances have been updated. To accept the transfer(s), this must return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81, or its own function selector). @param operator The address which initiated the batch transfer (i.e. msg.sender) @param from The address which previously owned the token @param ids An array containing ids of each token being transferred (order and length must match values array) @param values An array containing amounts of each token being transferred (order and length must match ids array) @param data Additional data with no specified format @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); } // Part: OpenZeppelin/[email protected]/IERC20Metadata /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // Part: OpenZeppelin/[email protected]/IERC721 /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; } // Part: OpenZeppelin/[email protected]/SafeERC20 /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // Part: OpenZeppelin/[email protected]/ERC1155Receiver /** * @dev _Available since v3.1._ */ abstract contract ERC1155Receiver is ERC165, IERC1155Receiver { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); } } // Part: OpenZeppelin/[email protected]/ERC20 /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); unchecked { _approve(sender, _msgSender(), currentAllowance - amount); } return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); _afterTokenTransfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} } // Part: OpenZeppelin/[email protected]/ERC1155Holder /** * @dev _Available since v3.1._ */ contract ERC1155Holder is ERC1155Receiver { function onERC1155Received( address, address, uint256, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] memory, uint256[] memory, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155BatchReceived.selector; } } // File: Registry.sol // @@@@@@@@@@@@@@@@ ,@@@@@@@@@@@@@@@@ // @@@,,,,,,,,,,@@@ ,@@&,,,,,,,,,,@@@ // @@@@@@@@,,,,,,,,,,@@@@@@@@& ,@@&,,,,,,,,,,@@@@@@@@ // @@@**********@@@@@@@@@@@@@& ,@@@@@@@@**********@@@ // @@@**********@@@@@@@@@@@@@& ,@@@@@@@@**********@@@@@@@@ // @@@**********@@@@@@@@@@@@@& .@@@**********@@@@@@@@ // @@@@@@@@**********@@@@@@@@@@@@@& .@@@**********@@@@@@@@ // @@@**********@@@@@@@@@@@@@& .@@@@@@@@**********@@@ // @@@**********@@@@@@@@@@@@@& .@@@@@@@@**********@@@@@@@@ // @@@@@@@@**********@@@@@@@@& .@@@**********@@@@@@@@@@@@@ // @@@@@@@@//////////@@@@@@@@& .@@@//////////@@@@@@@@@@@@@ // @@@//////////@@@@@@@@& .@@@//////////@@@@@@@@@@@@@ // @@@//////////@@@@@@@@& ,@@@@@@@@//////////@@@@@@@@@@@@@ // @@@%%%%%/////(((((@@@& ,@@@(((((/////%%%%%@@@@@@@@ // @@@@@@@@//////////@@@@@@@@& ,@@@//////////@@@@@@@@@@@@@ // @@@%%%%%%%%%%@@@@@@@@& ,@@@%%%%%%%%%%@@@@@@@@@@@@@ // @@@@@@@@@@@@@@@@@@@@@& ,@@@@@@@@@@@@@@@@@@@@@@@@@@ // @@@@@@@@@@@@@@@@& @@@@@@@@@@@@@@@@ // @@@@@@@@@@@@@@@@& @@@@@@@@@@@@@@@@ contract Registry is IRegistry, ERC721Holder, ERC1155Receiver, ERC1155Holder { using SafeERC20 for ERC20; IResolver private resolver; address private admin; address payable private beneficiary; uint256 private lendingID = 1; uint256 private rentingID = 1; bool public paused = false; uint256 public rentFee = 0; uint256 private constant SECONDS_IN_DAY = 86400; mapping(bytes32 => Lending) private lendings; mapping(bytes32 => Renting) private rentings; modifier onlyAdmin() { require(msg.sender == admin, "ReNFT::not admin"); _; } modifier notPaused() { require(!paused, "ReNFT::paused"); _; } constructor( address newResolver, address payable newBeneficiary, address newAdmin ) { ensureIsNotZeroAddr(newResolver); ensureIsNotZeroAddr(newBeneficiary); ensureIsNotZeroAddr(newAdmin); resolver = IResolver(newResolver); beneficiary = newBeneficiary; admin = newAdmin; } function lend( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory lendAmount, uint8[] memory maxRentDuration, bytes4[] memory dailyRentPrice, IResolver.PaymentToken[] memory paymentToken ) external override notPaused { bundleCall( handleLend, createLendCallData( nftStandard, nftAddress, tokenID, lendAmount, maxRentDuration, dailyRentPrice, paymentToken ) ); } function stopLend( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory _lendingID ) external override notPaused { bundleCall( handleStopLend, createActionCallData( nftStandard, nftAddress, tokenID, _lendingID, new uint256[](0) ) ); } function rent( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory _lendingID, uint8[] memory rentDuration, uint256[] memory rentAmount ) external payable override notPaused { bundleCall( handleRent, createRentCallData( nftStandard, nftAddress, tokenID, _lendingID, rentDuration, rentAmount ) ); } function stopRent( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory _lendingID, uint256[] memory _rentingID ) external override notPaused { bundleCall( handleStopRent, createActionCallData( nftStandard, nftAddress, tokenID, _lendingID, _rentingID ) ); } function claimRent( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory _lendingID, uint256[] memory _rentingID ) external override notPaused { bundleCall( handleClaimRent, createActionCallData( nftStandard, nftAddress, tokenID, _lendingID, _rentingID ) ); } // .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. // `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' function handleLend(IRegistry.CallData memory cd) private { for (uint256 i = cd.left; i < cd.right; i++) { ensureIsLendable(cd, i); bytes32 identifier = keccak256( abi.encodePacked( cd.nftAddress[cd.left], cd.tokenID[i], lendingID ) ); IRegistry.Lending storage lending = lendings[identifier]; ensureIsNull(lending); ensureTokenNotSentinel(uint8(cd.paymentToken[i])); bool is721 = cd.nftStandard[i] == IRegistry.NFTStandard.E721; lendings[identifier] = IRegistry.Lending({ nftStandard: cd.nftStandard[i], lenderAddress: payable(msg.sender), maxRentDuration: cd.maxRentDuration[i], dailyRentPrice: cd.dailyRentPrice[i], lendAmount: is721 ? 1 : uint16(cd.lendAmount[i]), availableAmount: is721 ? 1 : uint16(cd.lendAmount[i]), paymentToken: cd.paymentToken[i] }); emit IRegistry.Lend( is721, msg.sender, cd.nftAddress[cd.left], cd.tokenID[i], lendingID, cd.maxRentDuration[i], cd.dailyRentPrice[i], is721 ? 1 : uint16(cd.lendAmount[i]), cd.paymentToken[i] ); lendingID++; } safeTransfer( cd, msg.sender, address(this), sliceArr(cd.tokenID, cd.left, cd.right, 0), sliceArr(cd.lendAmount, cd.left, cd.right, 0) ); } function handleStopLend(IRegistry.CallData memory cd) private { uint256[] memory lentAmounts = new uint256[](cd.right - cd.left); for (uint256 i = cd.left; i < cd.right; i++) { bytes32 lendingIdentifier = keccak256( abi.encodePacked( cd.nftAddress[cd.left], cd.tokenID[i], cd.lendingID[i] ) ); Lending storage lending = lendings[lendingIdentifier]; ensureIsNotNull(lending); ensureIsStoppable(lending, msg.sender); require( cd.nftStandard[i] == lending.nftStandard, "ReNFT::invalid nft standard" ); require( lending.lendAmount == lending.availableAmount, "ReNFT::actively rented" ); lentAmounts[i - cd.left] = lending.lendAmount; emit IRegistry.StopLend(cd.lendingID[i], uint32(block.timestamp)); delete lendings[lendingIdentifier]; } safeTransfer( cd, address(this), msg.sender, sliceArr(cd.tokenID, cd.left, cd.right, 0), sliceArr(lentAmounts, cd.left, cd.right, cd.left) ); } function handleRent(IRegistry.CallData memory cd) private { for (uint256 i = cd.left; i < cd.right; i++) { bytes32 lendingIdentifier = keccak256( abi.encodePacked( cd.nftAddress[cd.left], cd.tokenID[i], cd.lendingID[i] ) ); bytes32 rentingIdentifier = keccak256( abi.encodePacked( cd.nftAddress[cd.left], cd.tokenID[i], rentingID ) ); IRegistry.Lending storage lending = lendings[lendingIdentifier]; IRegistry.Renting storage renting = rentings[rentingIdentifier]; ensureIsNotNull(lending); ensureIsNull(renting); ensureIsRentable(lending, cd, i, msg.sender); require( cd.nftStandard[i] == lending.nftStandard, "ReNFT::invalid nft standard" ); require( cd.rentAmount[i] <= lending.availableAmount, "ReNFT::invalid rent amount" ); uint8 paymentTokenIx = uint8(lending.paymentToken); address paymentToken = resolver.getPaymentToken(paymentTokenIx); uint256 decimals = ERC20(paymentToken).decimals(); { uint256 scale = 10**decimals; uint256 rentPrice = cd.rentAmount[i] * cd.rentDuration[i] * unpackPrice(lending.dailyRentPrice, scale); require(rentPrice > 0, "ReNFT::rent price is zero"); ERC20(paymentToken).safeTransferFrom( msg.sender, address(this), rentPrice ); } rentings[rentingIdentifier] = IRegistry.Renting({ renterAddress: payable(msg.sender), rentAmount: uint16(cd.rentAmount[i]), rentDuration: cd.rentDuration[i], rentedAt: uint32(block.timestamp) }); lendings[lendingIdentifier].availableAmount -= uint16( cd.rentAmount[i] ); emit IRegistry.Rent( msg.sender, cd.lendingID[i], rentingID, uint16(cd.rentAmount[i]), cd.rentDuration[i], renting.rentedAt ); rentingID++; } } function handleStopRent(IRegistry.CallData memory cd) private { for (uint256 i = cd.left; i < cd.right; i++) { bytes32 lendingIdentifier = keccak256( abi.encodePacked( cd.nftAddress[cd.left], cd.tokenID[i], cd.lendingID[i] ) ); bytes32 rentingIdentifier = keccak256( abi.encodePacked( cd.nftAddress[cd.left], cd.tokenID[i], cd.rentingID[i] ) ); IRegistry.Lending storage lending = lendings[lendingIdentifier]; IRegistry.Renting storage renting = rentings[rentingIdentifier]; ensureIsNotNull(lending); ensureIsNotNull(renting); ensureIsReturnable(renting, msg.sender, block.timestamp); require( cd.nftStandard[i] == lending.nftStandard, "ReNFT::invalid nft standard" ); require( renting.rentAmount <= lending.lendAmount, "ReNFT::critical error" ); uint256 secondsSinceRentStart = block.timestamp - renting.rentedAt; distributePayments(lending, renting, secondsSinceRentStart); lendings[lendingIdentifier].availableAmount += renting.rentAmount; emit IRegistry.StopRent(cd.rentingID[i], uint32(block.timestamp)); delete rentings[rentingIdentifier]; } } function handleClaimRent(CallData memory cd) private { for (uint256 i = cd.left; i < cd.right; i++) { bytes32 lendingIdentifier = keccak256( abi.encodePacked( cd.nftAddress[cd.left], cd.tokenID[i], cd.lendingID[i] ) ); bytes32 rentingIdentifier = keccak256( abi.encodePacked( cd.nftAddress[cd.left], cd.tokenID[i], cd.rentingID[i] ) ); IRegistry.Lending storage lending = lendings[lendingIdentifier]; IRegistry.Renting storage renting = rentings[rentingIdentifier]; ensureIsNotNull(lending); ensureIsNotNull(renting); ensureIsClaimable(renting, block.timestamp); distributeClaimPayment(lending, renting); lending.availableAmount += renting.rentAmount; emit IRegistry.RentClaimed( cd.rentingID[i], uint32(block.timestamp) ); delete rentings[rentingIdentifier]; } } // .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. // `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' function bundleCall( function(IRegistry.CallData memory) handler, IRegistry.CallData memory cd ) private { require(cd.nftAddress.length > 0, "ReNFT::no nfts"); while (cd.right != cd.nftAddress.length) { if ( (cd.nftAddress[cd.left] == cd.nftAddress[cd.right]) && (cd.nftStandard[cd.right] == IRegistry.NFTStandard.E1155) ) { cd.right++; } else { handler(cd); cd.left = cd.right; cd.right++; } } handler(cd); } function takeFee(uint256 rentAmt, IResolver.PaymentToken paymentToken) private returns (uint256 fee) { fee = rentAmt * rentFee; fee /= 10000; uint8 paymentTokenIx = uint8(paymentToken); ERC20 pmtToken = ERC20(resolver.getPaymentToken(paymentTokenIx)); pmtToken.safeTransfer(beneficiary, fee); } function distributePayments( IRegistry.Lending memory lending, IRegistry.Renting memory renting, uint256 secondsSinceRentStart ) private { uint8 paymentTokenIx = uint8(lending.paymentToken); address pmtToken = resolver.getPaymentToken(paymentTokenIx); uint256 decimals = ERC20(pmtToken).decimals(); uint256 scale = 10**decimals; uint256 rentPrice = renting.rentAmount * unpackPrice(lending.dailyRentPrice, scale); uint256 totalRenterPmt = rentPrice * renting.rentDuration; uint256 sendLenderAmt = (secondsSinceRentStart * rentPrice) / SECONDS_IN_DAY; require(totalRenterPmt > 0, "ReNFT::total renter payment is zero"); require(sendLenderAmt > 0, "ReNFT::lender payment is zero"); uint256 sendRenterAmt = totalRenterPmt - sendLenderAmt; if (rentFee != 0) { uint256 takenFee = takeFee(sendLenderAmt, lending.paymentToken); sendLenderAmt -= takenFee; } ERC20(pmtToken).safeTransfer(lending.lenderAddress, sendLenderAmt); if (sendRenterAmt > 0) { ERC20(pmtToken).safeTransfer(renting.renterAddress, sendRenterAmt); } } function distributeClaimPayment( IRegistry.Lending memory lending, IRegistry.Renting memory renting ) private { uint8 paymentTokenIx = uint8(lending.paymentToken); ERC20 paymentToken = ERC20(resolver.getPaymentToken(paymentTokenIx)); uint256 decimals = ERC20(paymentToken).decimals(); uint256 scale = 10**decimals; uint256 rentPrice = renting.rentAmount * unpackPrice(lending.dailyRentPrice, scale); uint256 finalAmt = rentPrice * renting.rentDuration; uint256 takenFee = 0; if (rentFee != 0) { takenFee = takeFee( finalAmt, IResolver.PaymentToken(paymentTokenIx) ); } paymentToken.safeTransfer(lending.lenderAddress, finalAmt - takenFee); } function safeTransfer( CallData memory cd, address from, address to, uint256[] memory tokenID, uint256[] memory lendAmount ) private { if (cd.nftStandard[cd.left] == IRegistry.NFTStandard.E721) { IERC721(cd.nftAddress[cd.left]).transferFrom( from, to, cd.tokenID[cd.left] ); } else { IERC1155(cd.nftAddress[cd.left]).safeBatchTransferFrom( from, to, tokenID, lendAmount, "" ); } } // .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. // `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' function getLending( address nftAddress, uint256 tokenID, uint256 _lendingID ) external view returns ( uint8, address, uint8, bytes4, uint16, uint16, uint8 ) { bytes32 identifier = keccak256( abi.encodePacked(nftAddress, tokenID, _lendingID) ); IRegistry.Lending storage lending = lendings[identifier]; return ( uint8(lending.nftStandard), lending.lenderAddress, lending.maxRentDuration, lending.dailyRentPrice, lending.lendAmount, lending.availableAmount, uint8(lending.paymentToken) ); } function getRenting( address nftAddress, uint256 tokenID, uint256 _rentingID ) external view returns ( address, uint16, uint8, uint32 ) { bytes32 identifier = keccak256( abi.encodePacked(nftAddress, tokenID, _rentingID) ); IRegistry.Renting storage renting = rentings[identifier]; return ( renting.renterAddress, renting.rentAmount, renting.rentDuration, renting.rentedAt ); } // .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. // `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' function createLendCallData( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory lendAmount, uint8[] memory maxRentDuration, bytes4[] memory dailyRentPrice, IResolver.PaymentToken[] memory paymentToken ) private pure returns (CallData memory cd) { cd = CallData({ left: 0, right: 1, nftStandard: nftStandard, nftAddress: nftAddress, tokenID: tokenID, lendAmount: lendAmount, lendingID: new uint256[](0), rentingID: new uint256[](0), rentDuration: new uint8[](0), rentAmount: new uint256[](0), maxRentDuration: maxRentDuration, dailyRentPrice: dailyRentPrice, paymentToken: paymentToken }); } function createRentCallData( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory _lendingID, uint8[] memory rentDuration, uint256[] memory rentAmount ) private pure returns (CallData memory cd) { cd = CallData({ left: 0, right: 1, nftStandard: nftStandard, nftAddress: nftAddress, tokenID: tokenID, lendAmount: new uint256[](0), lendingID: _lendingID, rentingID: new uint256[](0), rentDuration: rentDuration, rentAmount: rentAmount, maxRentDuration: new uint8[](0), dailyRentPrice: new bytes4[](0), paymentToken: new IResolver.PaymentToken[](0) }); } function createActionCallData( IRegistry.NFTStandard[] memory nftStandard, address[] memory nftAddress, uint256[] memory tokenID, uint256[] memory _lendingID, uint256[] memory _rentingID ) private pure returns (CallData memory cd) { cd = CallData({ left: 0, right: 1, nftStandard: nftStandard, nftAddress: nftAddress, tokenID: tokenID, lendAmount: new uint256[](0), lendingID: _lendingID, rentingID: _rentingID, rentDuration: new uint8[](0), rentAmount: new uint256[](0), maxRentDuration: new uint8[](0), dailyRentPrice: new bytes4[](0), paymentToken: new IResolver.PaymentToken[](0) }); } function unpackPrice(bytes4 price, uint256 scale) private pure returns (uint256) { ensureIsUnpackablePrice(price, scale); uint16 whole = uint16(bytes2(price)); uint16 decimal = uint16(bytes2(price << 16)); uint256 decimalScale = scale / 10000; if (whole > 9999) { whole = 9999; } if (decimal > 9999) { decimal = 9999; } uint256 w = whole * scale; uint256 d = decimal * decimalScale; uint256 fullPrice = w + d; return fullPrice; } function sliceArr( uint256[] memory arr, uint256 fromIx, uint256 toIx, uint256 arrOffset ) private pure returns (uint256[] memory r) { r = new uint256[](toIx - fromIx); for (uint256 i = fromIx; i < toIx; i++) { r[i - fromIx] = arr[i - arrOffset]; } } // .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. // `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' function ensureIsNotZeroAddr(address addr) private pure { require(addr != address(0), "ReNFT::zero address"); } function ensureIsZeroAddr(address addr) private pure { require(addr == address(0), "ReNFT::not a zero address"); } function ensureIsNull(Lending memory lending) private pure { ensureIsZeroAddr(lending.lenderAddress); require(lending.maxRentDuration == 0, "ReNFT::duration not zero"); require(lending.dailyRentPrice == 0, "ReNFT::rent price not zero"); } function ensureIsNotNull(Lending memory lending) private pure { ensureIsNotZeroAddr(lending.lenderAddress); require(lending.maxRentDuration != 0, "ReNFT::duration zero"); require(lending.dailyRentPrice != 0, "ReNFT::rent price is zero"); } function ensureIsNull(Renting memory renting) private pure { ensureIsZeroAddr(renting.renterAddress); require(renting.rentDuration == 0, "ReNFT::duration not zero"); require(renting.rentedAt == 0, "ReNFT::rented at not zero"); } function ensureIsNotNull(Renting memory renting) private pure { ensureIsNotZeroAddr(renting.renterAddress); require(renting.rentDuration != 0, "ReNFT::duration is zero"); require(renting.rentedAt != 0, "ReNFT::rented at is zero"); } function ensureIsLendable(CallData memory cd, uint256 i) private pure { require(cd.lendAmount[i] > 0, "ReNFT::lend amount is zero"); require(cd.lendAmount[i] <= type(uint16).max, "ReNFT::not uint16"); require(cd.maxRentDuration[i] > 0, "ReNFT::duration is zero"); require(cd.maxRentDuration[i] <= type(uint8).max, "ReNFT::not uint8"); require(uint32(cd.dailyRentPrice[i]) > 0, "ReNFT::rent price is zero"); } function ensureIsRentable( Lending memory lending, CallData memory cd, uint256 i, address msgSender ) private pure { require(msgSender != lending.lenderAddress, "ReNFT::cant rent own nft"); require(cd.rentDuration[i] <= type(uint8).max, "ReNFT::not uint8"); require(cd.rentDuration[i] > 0, "ReNFT::duration is zero"); require(cd.rentAmount[i] <= type(uint16).max, "ReNFT::not uint16"); require(cd.rentAmount[i] > 0, "ReNFT::rentAmount is zero"); require( cd.rentDuration[i] <= lending.maxRentDuration, "ReNFT::rent duration exceeds allowed max" ); } function ensureIsReturnable( Renting memory renting, address msgSender, uint256 blockTimestamp ) private pure { require(renting.renterAddress == msgSender, "ReNFT::not renter"); require( !isPastReturnDate(renting, blockTimestamp), "ReNFT::past return date" ); } function ensureIsStoppable(Lending memory lending, address msgSender) private pure { require(lending.lenderAddress == msgSender, "ReNFT::not lender"); } function ensureIsUnpackablePrice(bytes4 price, uint256 scale) private pure { require(uint32(price) > 0, "ReNFT::invalid price"); require(scale >= 10000, "ReNFT::invalid scale"); } function ensureTokenNotSentinel(uint8 paymentIx) private pure { require(paymentIx > 0, "ReNFT::token is sentinel"); } function ensureIsClaimable( IRegistry.Renting memory renting, uint256 blockTimestamp ) private pure { require( isPastReturnDate(renting, blockTimestamp), "ReNFT::return date not passed" ); } function isPastReturnDate(Renting memory renting, uint256 nowTime) private pure returns (bool) { require(nowTime > renting.rentedAt, "ReNFT::now before rented"); return nowTime - renting.rentedAt > renting.rentDuration * SECONDS_IN_DAY; } // .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. // `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' `._.' function setRentFee(uint256 newRentFee) external onlyAdmin { require(newRentFee < 10000, "ReNFT::fee exceeds 100pct"); rentFee = newRentFee; } function setBeneficiary(address payable newBeneficiary) external onlyAdmin { beneficiary = newBeneficiary; } function setPaused(bool newPaused) external onlyAdmin { paused = newPaused; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"newResolver","type":"address"},{"internalType":"address payable","name":"newBeneficiary","type":"address"},{"internalType":"address","name":"newAdmin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"is721","type":"bool"},{"indexed":true,"internalType":"address","name":"lenderAddress","type":"address"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lendingID","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"maxRentDuration","type":"uint8"},{"indexed":false,"internalType":"bytes4","name":"dailyRentPrice","type":"bytes4"},{"indexed":false,"internalType":"uint16","name":"lendAmount","type":"uint16"},{"indexed":false,"internalType":"enum IResolver.PaymentToken","name":"paymentToken","type":"uint8"}],"name":"Lend","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"renterAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"lendingID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"rentingID","type":"uint256"},{"indexed":false,"internalType":"uint16","name":"rentAmount","type":"uint16"},{"indexed":false,"internalType":"uint8","name":"rentDuration","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"rentedAt","type":"uint32"}],"name":"Rent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"rentingID","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"collectedAt","type":"uint32"}],"name":"RentClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"lendingID","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"stoppedAt","type":"uint32"}],"name":"StopLend","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"rentingID","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"stoppedAt","type":"uint32"}],"name":"StopRent","type":"event"},{"inputs":[{"internalType":"enum IRegistry.NFTStandard[]","name":"nftStandard","type":"uint8[]"},{"internalType":"address[]","name":"nftAddress","type":"address[]"},{"internalType":"uint256[]","name":"tokenID","type":"uint256[]"},{"internalType":"uint256[]","name":"_lendingID","type":"uint256[]"},{"internalType":"uint256[]","name":"_rentingID","type":"uint256[]"}],"name":"claimRent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenID","type":"uint256"},{"internalType":"uint256","name":"_lendingID","type":"uint256"}],"name":"getLending","outputs":[{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"bytes4","name":"","type":"bytes4"},{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenID","type":"uint256"},{"internalType":"uint256","name":"_rentingID","type":"uint256"}],"name":"getRenting","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IRegistry.NFTStandard[]","name":"nftStandard","type":"uint8[]"},{"internalType":"address[]","name":"nftAddress","type":"address[]"},{"internalType":"uint256[]","name":"tokenID","type":"uint256[]"},{"internalType":"uint256[]","name":"lendAmount","type":"uint256[]"},{"internalType":"uint8[]","name":"maxRentDuration","type":"uint8[]"},{"internalType":"bytes4[]","name":"dailyRentPrice","type":"bytes4[]"},{"internalType":"enum IResolver.PaymentToken[]","name":"paymentToken","type":"uint8[]"}],"name":"lend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IRegistry.NFTStandard[]","name":"nftStandard","type":"uint8[]"},{"internalType":"address[]","name":"nftAddress","type":"address[]"},{"internalType":"uint256[]","name":"tokenID","type":"uint256[]"},{"internalType":"uint256[]","name":"_lendingID","type":"uint256[]"},{"internalType":"uint8[]","name":"rentDuration","type":"uint8[]"},{"internalType":"uint256[]","name":"rentAmount","type":"uint256[]"}],"name":"rent","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"rentFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"newBeneficiary","type":"address"}],"name":"setBeneficiary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"newPaused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRentFee","type":"uint256"}],"name":"setRentFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IRegistry.NFTStandard[]","name":"nftStandard","type":"uint8[]"},{"internalType":"address[]","name":"nftAddress","type":"address[]"},{"internalType":"uint256[]","name":"tokenID","type":"uint256[]"},{"internalType":"uint256[]","name":"_lendingID","type":"uint256[]"}],"name":"stopLend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IRegistry.NFTStandard[]","name":"nftStandard","type":"uint8[]"},{"internalType":"address[]","name":"nftAddress","type":"address[]"},{"internalType":"uint256[]","name":"tokenID","type":"uint256[]"},{"internalType":"uint256[]","name":"_lendingID","type":"uint256[]"},{"internalType":"uint256[]","name":"_rentingID","type":"uint256[]"}],"name":"stopRent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052600160038190556004556005805460ff1916905560006006553480156200002a57600080fd5b5060405162004cc038038062004cc08339810160408190526200004d916200010f565b6200005883620000b1565b6200006382620000b1565b6200006e81620000b1565b600080546001600160a01b039485166001600160a01b03199182161790915560028054938516938216939093179092556001805491909316911617905562000179565b6001600160a01b0381166200010c5760405162461bcd60e51b815260206004820152601360248201527f52654e46543a3a7a65726f206164647265737300000000000000000000000000604482015260640160405180910390fd5b50565b6000806000606084860312156200012557600080fd5b8351620001328162000163565b6020850151909350620001458162000163565b6040850151909250620001588162000163565b809150509250925092565b6001600160a01b03811681146200010c57600080fd5b614b3780620001896000396000f3fe6080604052600436106100f35760003560e01c806376774ea31161008a578063c9c4018311610059578063c9c4018314610315578063cbe55e5414610335578063f23a6e6114610348578063fe46b7cd1461037457600080fd5b806376774ea314610285578063937821a1146102a5578063bc197c81146102c5578063bf2b23ea146102f157600080fd5b80631c31f710116100c65780631c31f710146101b35780631cbb410f146101d3578063296c21b7146101f35780635c975abb1461026b57600080fd5b806301ffc9a7146100f857806314b5685c1461012d578063150b7a021461014f57806316c38b3c14610193575b600080fd5b34801561010457600080fd5b50610118610113366004614581565b6103cf565b60405190151581526020015b60405180910390f35b34801561013957600080fd5b5061014d610148366004614275565b610406565b005b34801561015b57600080fd5b5061017a61016a3660046140cd565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610124565b34801561019f57600080fd5b5061014d6101ae366004614547565b610451565b3480156101bf57600080fd5b5061014d6101ce366004614003565b61048e565b3480156101df57600080fd5b5061014d6101ee366004614339565b6104da565b3480156101ff57600080fd5b5061021361020e3660046141a0565b61051b565b6040805160ff98891681526001600160a01b039097166020880152948716948601949094526001600160e01b0319909216606085015261ffff90811660808501521660a08301529190911660c082015260e001610124565b34801561027757600080fd5b506005546101189060ff1681565b34801561029157600080fd5b5061014d6102a036600461459c565b6105f1565b3480156102b157600080fd5b5061014d6102c0366004614275565b610671565b3480156102d157600080fd5b5061017a6102e0366004614020565b63bc197c8160e01b95945050505050565b3480156102fd57600080fd5b5061030760065481565b604051908152602001610124565b34801561032157600080fd5b5061014d6103303660046141d5565b6106a7565b61014d610343366004614453565b61070e565b34801561035457600080fd5b5061017a610363366004614138565b63f23a6e6160e01b95945050505050565b34801561038057600080fd5b5061039461038f3660046141a0565b61074d565b604080516001600160a01b03909516855261ffff909316602085015260ff9091169183019190915263ffffffff166060820152608001610124565b60006001600160e01b03198216630271189760e51b148061040057506301ffc9a760e01b6001600160e01b03198316145b92915050565b60055460ff16156104325760405162461bcd60e51b8152600401610429906147e8565b60405180910390fd5b61044a6107cb6104458787878787610d6d565b610ef3565b5050505050565b6001546001600160a01b0316331461047b5760405162461bcd60e51b81526004016104299061480f565b6005805460ff1916911515919091179055565b6001546001600160a01b031633146104b85760405162461bcd60e51b81526004016104299061480f565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b60055460ff16156104fd5760405162461bcd60e51b8152600401610429906147e8565b610512611028610445898989898989896115cb565b50505050505050565b6000806000806000806000808a8a8a60405160200161053c9392919061460d565b60408051601f19818403018152918152815160209283012060008181526007909352912080549192509060ff16600181111561057a5761057a614a8d565b81546001600160a01b036101008204169060ff600160a81b8204811691600160b01b810460e01b9161ffff600160d01b8304811692600160e01b810490911691600160f01b9091041660038111156105d4576105d4614a8d565b985098509850985098509850985050509397509397509397909450565b6001546001600160a01b0316331461061b5760405162461bcd60e51b81526004016104299061480f565b612710811061066c5760405162461bcd60e51b815260206004820152601960248201527f52654e46543a3a666565206578636565647320313030706374000000000000006044820152606401610429565b600655565b60055460ff16156106945760405162461bcd60e51b8152600401610429906147e8565b61044a6116fb6104458787878787610d6d565b60055460ff16156106ca5760405162461bcd60e51b8152600401610429906147e8565b610708611b02610445868686866000604051908082528060200260200182016040528015610702578160200160208202803683370190505b50610d6d565b50505050565b60055460ff16156107315760405162461bcd60e51b8152600401610429906147e8565b610745611ebb61044588888888888861263c565b505050505050565b600080600080600087878760405160200161076a9392919061460d565b60408051808303601f190181529181528151602092830120600090815260089092529020546001600160a01b03811699600160c81b820461ffff169950600160a01b820460ff169850600160a81b90910463ffffffff169650945050505050565b80515b8160200151811015610d6957600082606001518360000151815181106107f6576107f6614aa3565b60200260200101518360800151838151811061081457610814614aa3565b6020026020010151846101000151848151811061083357610833614aa3565b602002602001015160405160200161084d9392919061460d565b6040516020818303038152906040528051906020012090506000836060015184600001518151811061088157610881614aa3565b60200260200101518460800151848151811061089f5761089f614aa3565b602002602001015185610120015185815181106108be576108be614aa3565b60200260200101516040516020016108d89392919061460d565b60408051601f198184030181528282528051602091820120600086815260078352838120828252600890935283902060e08501909352815490945090926109d9918490829060ff16600181111561093157610931614a8d565b600181111561094257610942614a8d565b815281546001600160a01b03610100820416602083015260ff600160a81b8204811660408401526001600160e01b0319600160b01b830460e01b16606084015261ffff600160d01b830481166080850152600160e01b83041660a084015260c090920191600160f01b9091041660038111156109c0576109c0614a8d565b60038111156109d1576109d1614a8d565b90525061275e565b6040805160808101825282546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff166060820152610a2e906127e1565b6040805160808101825282546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff166060820152610a85903342612867565b815460ff166001811115610a9b57610a9b614a8d565b86604001518681518110610ab157610ab1614aa3565b60200260200101516001811115610aca57610aca614a8d565b14610ae75760405162461bcd60e51b815260040161042990614743565b81548154600160d01b90910461ffff908116600160c81b909204161115610b485760405162461bcd60e51b81526020600482015260156024820152742932a7232a1d1d31b934ba34b1b0b61032b93937b960591b6044820152606401610429565b8054600090610b6490600160a81b900463ffffffff1642614a19565b6040805160e081019091528454919250610c85918590829060ff166001811115610b9057610b90614a8d565b6001811115610ba157610ba1614a8d565b815281546001600160a01b03610100820416602083015260ff600160a81b8204811660408401526001600160e01b0319600160b01b830460e01b16606084015261ffff600160d01b830481166080850152600160e01b83041660a084015260c090920191600160f01b909104166003811115610c1f57610c1f614a8d565b6003811115610c3057610c30614a8d565b9052506040805160808101825285546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff1660608201528361291c565b81546000868152600760205260409020805461ffff600160c81b909304831692601c91610cbb918591600160e01b90041661488c565b92506101000a81548161ffff021916908361ffff1602179055508661012001518681518110610cec57610cec614aa3565b60200260200101517f58855dd8908b14c6d7922d964418f37efd968bc6b9b857560870b14a898f916d42604051610d2f919063ffffffff91909116815260200190565b60405180910390a2505050600090815260086020526040902080546001600160d81b03191690555080610d6181614a5c565b9150506107ce565b5050565b610d75613c5f565b604051806101a00160405280600081526020016001815260200187815260200186815260200185815260200160006001600160401b03811115610dba57610dba614ab9565b604051908082528060200260200182016040528015610de3578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610e14578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610e45578160200160208202803683370190505b50815260208101859052604081018490526060016000604051908082528060200260200182016040528015610e84578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610eb5578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610ee6578160200160208202803683370190505b5090529695505050505050565b600081606001515111610f395760405162461bcd60e51b815260206004820152600e60248201526d52654e46543a3a6e6f206e66747360901b6044820152606401610429565b80606001515181602001511461101b578060600151816020015181518110610f6357610f63614aa3565b60200260200101516001600160a01b03168160600151826000015181518110610f8e57610f8e614aa3565b60200260200101516001600160a01b0316148015610fde575060018160400151826020015181518110610fc357610fc3614aa3565b60200260200101516001811115610fdc57610fdc614a8d565b145b15610ffb5760208101805190610ff382614a5c565b905250610f39565b611008818363ffffffff16565b60208101805180835290610ff382614a5c565b610d69818363ffffffff16565b80515b816020015181101561158a576110418282612bc1565b6000826060015183600001518151811061105d5761105d614aa3565b60200260200101518360800151838151811061107b5761107b614aa3565b60200260200101516003546040516020016110989392919061460d565b60408051601f198184030181528282528051602091820120600081815260079092529082902060e0840190925281549093509091611190918390829060ff1660018111156110e8576110e8614a8d565b60018111156110f9576110f9614a8d565b815281546001600160a01b03610100820416602083015260ff600160a81b8204811660408401526001600160e01b0319600160b01b830460e01b16606084015261ffff600160d01b830481166080850152600160e01b83041660a084015260c090920191600160f01b90910416600381111561117757611177614a8d565b600381111561118857611188614a8d565b905250612d7f565b6111c884610180015184815181106111aa576111aa614aa3565b602002602001015160038111156111c3576111c3614a8d565b612e38565b600080856040015185815181106111e1576111e1614aa3565b602002602001015160018111156111fa576111fa614a8d565b1490506040518060e001604052808660400151868151811061121e5761121e614aa3565b6020026020010151600181111561123757611237614a8d565b8152602001336001600160a01b031681526020018660c00151868151811061126157611261614aa3565b602002602001015160ff1681526020018660e00151868151811061128757611287614aa3565b60200260200101516001600160e01b0319168152602001826112c6578660a0015186815181106112b9576112b9614aa3565b60200260200101516112c9565b60015b61ffff168152602001826112fa578660a0015186815181106112ed576112ed614aa3565b60200260200101516112fd565b60015b61ffff168152602001866101800151868151811061131d5761131d614aa3565b6020026020010151600381111561133657611336614a8d565b9052600084815260076020526040902081518154829060ff19166001838181111561136357611363614a8d565b02179055506020820151815460408401516060850151608086015160a0870151610100600160b01b03199094166101006001600160a01b039096169590950260ff60a81b191694909417600160a81b60ff909316929092029190911765ffffffffffff60b01b1916600160b01b60e09290921c9190910261ffff60d01b191617600160d01b61ffff938416021761ffff60e01b198116600160e01b9390921692909202908117835560c084015191839162ffffff60e01b1990911660ff60f01b1990911617600160f01b83600381111561143f5761143f614a8d565b02179055509050508460800151848151811061145d5761145d614aa3565b6020026020010151856060015186600001518151811061147f5761147f614aa3565b60200260200101516001600160a01b0316336001600160a01b03167f46e173c7568bb4f093e16923381dcba2a6b48f9cc9e688867965731218500ad3846003548a60c001518a815181106114d5576114d5614aa3565b60200260200101518b60e001518b815181106114f3576114f3614aa3565b602002602001015188611523578c60a001518c8151811061151657611516614aa3565b6020026020010151611526565b60015b8d61018001518d8151811061153d5761153d614aa3565b6020026020010151604051611557969594939291906146ae565b60405180910390a46003805490600061156f83614a5c565b9190505550505050808061158290614a5c565b91505061102b565b506115c88133306115aa8560800151866000015187602001516000612e8b565b6115c38660a00151876000015188602001516000612e8b565b612f4a565b50565b6115d3613c5f565b604051806101a00160405280600081526020016001815260200189815260200188815260200187815260200186815260200185815260200184815260200160006001600160401b0381111561162a5761162a614ab9565b604051908082528060200260200182016040528015611653578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015611684578160200160208202803683370190505b50815260200160006040519080825280602002602001820160405280156116b5578160200160208202803683370190505b50815260200160006040519080825280602002602001820160405280156116e6578160200160208202803683370190505b50815260200192909252509695505050505050565b80515b8160200151811015610d69576000826060015183600001518151811061172657611726614aa3565b60200260200101518360800151838151811061174457611744614aa3565b6020026020010151846101000151848151811061176357611763614aa3565b602002602001015160405160200161177d9392919061460d565b604051602081830303815290604052805190602001209050600083606001518460000151815181106117b1576117b1614aa3565b6020026020010151846080015184815181106117cf576117cf614aa3565b602002602001015185610120015185815181106117ee576117ee614aa3565b60200260200101516040516020016118089392919061460d565b60408051601f198184030181528282528051602091820120600086815260078352838120828252600890935283902060e0850190935281549094509092611861918490829060ff16600181111561093157610931614a8d565b6040805160808101825282546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff1660608201526118b6906127e1565b6040805160808101825282546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff16606082015261190c90426130cb565b6040805160e081019091528254611a2a91908490829060ff16600181111561193657611936614a8d565b600181111561194757611947614a8d565b815281546001600160a01b03610100820416602083015260ff600160a81b8204811660408401526001600160e01b0319600160b01b830460e01b16606084015261ffff600160d01b830481166080850152600160e01b83041660a084015260c090920191600160f01b9091041660038111156119c5576119c5614a8d565b60038111156119d6576119d6614a8d565b9052506040805160808101825284546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff166060820152613121565b8054825461ffff600160c81b9092048216918491601c91611a55918591600160e01b9091041661488c565b92506101000a81548161ffff021916908361ffff1602179055508561012001518581518110611a8657611a86614aa3565b60200260200101517f4630b53a4335803b2a4f9c1ce896f4cadbf909907810e496eda17614483d7b9442604051611ac9919063ffffffff91909116815260200190565b60405180910390a25050600090815260086020526040902080546001600160d81b03191690555080611afa81614a5c565b9150506116fe565b80516020820151600091611b1591614a19565b6001600160401b03811115611b2c57611b2c614ab9565b604051908082528060200260200182016040528015611b55578160200160208202803683370190505b5082519091505b8260200151811015611e885760008360600151846000015181518110611b8457611b84614aa3565b602002602001015184608001518381518110611ba257611ba2614aa3565b60200260200101518561010001518481518110611bc157611bc1614aa3565b6020026020010151604051602001611bdb9392919061460d565b60408051601f198184030181528282528051602091820120600081815260079092529082902060e0840190925281549093509091611c2b918390829060ff16600181111561093157610931614a8d565b6040805160e081019091528154611cfe91908390829060ff166001811115611c5557611c55614a8d565b6001811115611c6657611c66614a8d565b815281546001600160a01b03610100820416602083015260ff600160a81b8204811660408401526001600160e01b0319600160b01b830460e01b16606084015261ffff600160d01b830481166080850152600160e01b83041660a084015260c090920191600160f01b909104166003811115611ce457611ce4614a8d565b6003811115611cf557611cf5614a8d565b905250336132d3565b805460ff166001811115611d1457611d14614a8d565b85604001518481518110611d2a57611d2a614aa3565b60200260200101516001811115611d4357611d43614a8d565b14611d605760405162461bcd60e51b815260040161042990614743565b8054600160d01b810461ffff908116600160e01b9092041614611dbe5760405162461bcd60e51b815260206004820152601660248201527514995391950e8e9858dd1a5d995b1e481c995b9d195960521b6044820152606401610429565b80548551600160d01b90910461ffff16908590611ddb9086614a19565b81518110611deb57611deb614aa3565b6020026020010181815250508461010001518381518110611e0e57611e0e614aa3565b60200260200101517fd0234bc8dd7e933f60cbc1e90fc139a8a9683af1cb92743607dafb9dfb70059b42604051611e51919063ffffffff91909116815260200190565b60405180910390a250600090815260076020526040902080546001600160f81b031916905580611e8081614a5c565b915050611b5c565b50610d69823033611ea88660800151876000015188602001516000612e8b565b865160208801516115c391889181612e8b565b80515b8160200151811015610d695760008260600151836000015181518110611ee657611ee6614aa3565b602002602001015183608001518381518110611f0457611f04614aa3565b60200260200101518461010001518481518110611f2357611f23614aa3565b6020026020010151604051602001611f3d9392919061460d565b60405160208183030381529060405280519060200120905060008360600151846000015181518110611f7157611f71614aa3565b602002602001015184608001518481518110611f8f57611f8f614aa3565b6020026020010151600454604051602001611fac9392919061460d565b60408051601f198184030181528282528051602091820120600086815260078352838120828252600890935283902060e0850190935281549094509092612005918490829060ff16600181111561093157610931614a8d565b6040805160808101825282546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff16606082015261205a9061332c565b6040805160e08101909152825461212f91908490829060ff16600181111561208457612084614a8d565b600181111561209557612095614a8d565b815281546001600160a01b03610100820416602083015260ff600160a81b8204811660408401526001600160e01b0319600160b01b830460e01b16606084015261ffff600160d01b830481166080850152600160e01b83041660a084015260c090920191600160f01b90910416600381111561211357612113614a8d565b600381111561212457612124614a8d565b9052508787336133df565b815460ff16600181111561214557612145614a8d565b8660400151868151811061215b5761215b614aa3565b6020026020010151600181111561217457612174614a8d565b146121915760405162461bcd60e51b815260040161042990614743565b81546101608701518051600160e01b90920461ffff1691879081106121b8576121b8614aa3565b6020026020010151111561220e5760405162461bcd60e51b815260206004820152601a60248201527f52654e46543a3a696e76616c69642072656e7420616d6f756e740000000000006044820152606401610429565b8154600090600160f01b900460ff16600381111561222e5761222e614a8d565b6000805460405163c6ee427f60e01b815260ff8416600482015292935090916001600160a01b039091169063c6ee427f9060240160206040518083038186803b15801561227a57600080fd5b505afa15801561228e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b29190613fe6565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156122ef57600080fd5b505afa158015612303573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232791906145b5565b60ff169050600061233982600a61492f565b865490915060009061235590600160b01b900460e01b8361364a565b8b61014001518b8151811061236c5761236c614aa3565b602002602001015160ff168c61016001518c8151811061238e5761238e614aa3565b60200260200101516123a091906149d7565b6123aa91906149d7565b9050600081116123cc5760405162461bcd60e51b8152600401610429906147b1565b6123e16001600160a01b0385163330846136d9565b50506040518060800160405280336001600160a01b031681526020018a61014001518a8151811061241457612414614aa3565b602002602001015160ff1681526020014263ffffffff1681526020018a61016001518a8151811061244757612447614aa3565b60209081029190910181015161ffff908116909252600089815260088252604090819020845181549386015192860151606090960151909416600160c81b0261ffff60c81b1963ffffffff909616600160a81b029590951665ffffffffffff60a81b1960ff909316600160a01b026001600160a81b03199094166001600160a01b03909516949094179290921716919091179190911790556101608901518051899081106124f7576124f7614aa3565b6020908102919091018101516000898152600790925260409091208054601c9061252d908490600160e01b900461ffff166149f6565b92506101000a81548161ffff021916908361ffff160217905550600454896101000151898151811061256157612561614aa3565b6020026020010151336001600160a01b03167f61e1a1e6f89eaba4ba0119b0023bd32b1bb0412ab96ccd8d0588a3e98a0976318c61016001518c815181106125ab576125ab614aa3565b60200260200101518d61014001518d815181106125ca576125ca614aa3565b6020908102919091018101518a546040805161ffff909516855260ff90921692840192909252600160a81b90910463ffffffff169082015260600160405180910390a46004805490600061261d83614a5c565b919050555050505050505050808061263490614a5c565b915050611ebe565b612644613c5f565b604051806101a00160405280600081526020016001815260200188815260200187815260200186815260200160006001600160401b0381111561268957612689614ab9565b6040519080825280602002602001820160405280156126b2578160200160208202803683370190505b50815260200160006040519080825280602002602001820160405280156126e3578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015612714578160200160208202803683370190505b5081526020808201969096526040805160008082528189018352828401919091526060830196909652608082019490945283519485529484019092525060a0909201529392505050565b61276b8160200151613744565b604081015160ff166127b65760405162461bcd60e51b815260206004820152601460248201527352654e46543a3a6475726174696f6e207a65726f60601b6044820152606401610429565b60608101516001600160e01b0319166115c85760405162461bcd60e51b8152600401610429906147b1565b80516127ec90613744565b602081015160ff166128105760405162461bcd60e51b81526004016104299061477a565b604081015163ffffffff166115c85760405162461bcd60e51b815260206004820152601860248201527f52654e46543a3a72656e746564206174206973207a65726f00000000000000006044820152606401610429565b816001600160a01b031683600001516001600160a01b0316146128c05760405162461bcd60e51b81526020600482015260116024820152702932a7232a1d1d3737ba103932b73a32b960791b6044820152606401610429565b6128ca8382613790565b156129175760405162461bcd60e51b815260206004820152601760248201527f52654e46543a3a706173742072657475726e20646174650000000000000000006044820152606401610429565b505050565b60008360c00151600381111561293457612934614a8d565b6000805460405163c6ee427f60e01b815260ff8416600482015292935090916001600160a01b039091169063c6ee427f9060240160206040518083038186803b15801561298057600080fd5b505afa158015612994573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b89190613fe6565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156129f557600080fd5b505afa158015612a09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2d91906145b5565b60ff1690506000612a3f82600a61492f565b90506000612a5188606001518361364a565b876060015161ffff16612a6491906149d7565b90506000876020015160ff1682612a7b91906149d7565b9050600062015180612a8d848a6149d7565b612a9791906148ca565b905060008211612af55760405162461bcd60e51b815260206004820152602360248201527f52654e46543a3a746f74616c2072656e746572207061796d656e74206973207a60448201526265726f60e81b6064820152608401610429565b60008111612b455760405162461bcd60e51b815260206004820152601d60248201527f52654e46543a3a6c656e646572207061796d656e74206973207a65726f0000006044820152606401610429565b6000612b518284614a19565b9050600654600014612b7d576000612b6d838d60c0015161381e565b9050612b798184614a19565b9250505b60208b0151612b97906001600160a01b03891690846138fb565b8015612bb4578951612bb4906001600160a01b03891690836138fb565b5050505050505050505050565b60008260a001518281518110612bd957612bd9614aa3565b602002602001015111612c2e5760405162461bcd60e51b815260206004820152601a60248201527f52654e46543a3a6c656e6420616d6f756e74206973207a65726f0000000000006044820152606401610429565b61ffff80168260a001518281518110612c4957612c49614aa3565b60200260200101511115612c935760405162461bcd60e51b81526020600482015260116024820152702932a7232a1d1d3737ba103ab4b73a189b60791b6044820152606401610429565b60008260c001518281518110612cab57612cab614aa3565b602002602001015160ff1611612cd35760405162461bcd60e51b81526004016104299061477a565b60ff80168260c001518281518110612ced57612ced614aa3565b602002602001015160ff161115612d395760405162461bcd60e51b815260206004820152601060248201526f0a4ca9c8ca87474dcdee840ead2dce8760831b6044820152606401610429565b60008260e001518281518110612d5157612d51614aa3565b602002602001015160e01c63ffffffff1611610d695760405162461bcd60e51b8152600401610429906147b1565b612d8c816020015161392b565b604081015160ff1615612ddc5760405162461bcd60e51b815260206004820152601860248201527752654e46543a3a6475726174696f6e206e6f74207a65726f60401b6044820152606401610429565b60608101516001600160e01b031916156115c85760405162461bcd60e51b815260206004820152601a60248201527f52654e46543a3a72656e74207072696365206e6f74207a65726f0000000000006044820152606401610429565b60008160ff16116115c85760405162461bcd60e51b815260206004820152601860248201527f52654e46543a3a746f6b656e2069732073656e74696e656c00000000000000006044820152606401610429565b6060612e978484614a19565b6001600160401b03811115612eae57612eae614ab9565b604051908082528060200260200182016040528015612ed7578160200160208202803683370190505b509050835b83811015612f415785612eef8483614a19565b81518110612eff57612eff614aa3565b6020026020010151828683612f149190614a19565b81518110612f2457612f24614aa3565b602090810291909101015280612f3981614a5c565b915050612edc565b50949350505050565b60006040860151865181518110612f6357612f63614aa3565b60200260200101516001811115612f7c57612f7c614a8d565b1415613042576060850151855181518110612f9957612f99614aa3565b60200260200101516001600160a01b03166323b872dd85858860800151896000015181518110612fcb57612fcb614aa3565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561302557600080fd5b505af1158015613039573d6000803e3d6000fd5b5050505061044a565b606085015185518151811061305957613059614aa3565b60200260200101516001600160a01b0316632eb2c2d6858585856040518563ffffffff1660e01b81526004016130929493929190614653565b600060405180830381600087803b1580156130ac57600080fd5b505af11580156130c0573d6000803e3d6000fd5b505050505050505050565b6130d58282613790565b610d695760405162461bcd60e51b815260206004820152601d60248201527f52654e46543a3a72657475726e2064617465206e6f74207061737365640000006044820152606401610429565b60008260c00151600381111561313957613139614a8d565b6000805460405163c6ee427f60e01b815260ff8416600482015292935090916001600160a01b039091169063c6ee427f9060240160206040518083038186803b15801561318557600080fd5b505afa158015613199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131bd9190613fe6565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156131fa57600080fd5b505afa15801561320e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061323291906145b5565b60ff169050600061324482600a61492f565b9050600061325687606001518361364a565b866060015161ffff1661326991906149d7565b90506000866020015160ff168261328091906149d7565b905060006006546000146132af576132ac828860ff1660038111156132a7576132a7614a8d565b61381e565b90505b60208901516130c0906132c28385614a19565b6001600160a01b03891691906138fb565b806001600160a01b031682602001516001600160a01b031614610d695760405162461bcd60e51b81526020600482015260116024820152702932a7232a1d1d3737ba103632b73232b960791b6044820152606401610429565b80516133379061392b565b602081015160ff16156133875760405162461bcd60e51b815260206004820152601860248201527752654e46543a3a6475726174696f6e206e6f74207a65726f60401b6044820152606401610429565b604081015163ffffffff16156115c85760405162461bcd60e51b815260206004820152601960248201527f52654e46543a3a72656e746564206174206e6f74207a65726f000000000000006044820152606401610429565b83602001516001600160a01b0316816001600160a01b031614156134455760405162461bcd60e51b815260206004820152601860248201527f52654e46543a3a63616e742072656e74206f776e206e667400000000000000006044820152606401610429565b60ff8016836101400151838151811061346057613460614aa3565b602002602001015160ff1611156134ac5760405162461bcd60e51b815260206004820152601060248201526f0a4ca9c8ca87474dcdee840ead2dce8760831b6044820152606401610429565b600083610140015183815181106134c5576134c5614aa3565b602002602001015160ff16116134ed5760405162461bcd60e51b81526004016104299061477a565b61ffff8016836101600151838151811061350957613509614aa3565b602002602001015111156135535760405162461bcd60e51b81526020600482015260116024820152702932a7232a1d1d3737ba103ab4b73a189b60791b6044820152606401610429565b6000836101600151838151811061356c5761356c614aa3565b6020026020010151116135c15760405162461bcd60e51b815260206004820152601960248201527f52654e46543a3a72656e74416d6f756e74206973207a65726f000000000000006044820152606401610429565b836040015160ff1683610140015183815181106135e0576135e0614aa3565b602002602001015160ff1611156107085760405162461bcd60e51b815260206004820152602860248201527f52654e46543a3a72656e74206475726174696f6e206578636565647320616c6c6044820152670deeecac840dac2f60c31b6064820152608401610429565b60006136568383613982565b60f083901c61ffff60e085901c166000613672612710866148ca565b905061270f8361ffff1611156136885761270f92505b61270f8261ffff16111561369c5761270f91505b60006136ac8661ffff86166149d7565b905060006136be8361ffff86166149d7565b905060006136cc82846148b2565b9998505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526107089085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613a13565b6001600160a01b0381166115c85760405162461bcd60e51b815260206004820152601360248201527252654e46543a3a7a65726f206164647265737360681b6044820152606401610429565b6000826040015163ffffffff1682116137eb5760405162461bcd60e51b815260206004820152601860248201527f52654e46543a3a6e6f77206265666f72652072656e74656400000000000000006044820152606401610429565b62015180836020015160ff1661380191906149d7565b60408401516138169063ffffffff1684614a19565b119392505050565b60006006548361382e91906149d7565b905061383c612710826148ca565b9050600082600381111561385257613852614a8d565b6000805460405163c6ee427f60e01b815260ff8416600482015292935090916001600160a01b039091169063c6ee427f9060240160206040518083038186803b15801561389e57600080fd5b505afa1580156138b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138d69190613fe6565b6002549091506138f3906001600160a01b038084169116856138fb565b505092915050565b6040516001600160a01b03831660248201526044810182905261291790849063a9059cbb60e01b9060640161370d565b6001600160a01b038116156115c85760405162461bcd60e51b815260206004820152601960248201527f52654e46543a3a6e6f742061207a65726f2061646472657373000000000000006044820152606401610429565b60e082901c6139ca5760405162461bcd60e51b815260206004820152601460248201527352654e46543a3a696e76616c696420707269636560601b6044820152606401610429565b612710811015610d695760405162461bcd60e51b815260206004820152601460248201527352654e46543a3a696e76616c6964207363616c6560601b6044820152606401610429565b6000613a68826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613ae59092919063ffffffff16565b8051909150156129175780806020019051810190613a869190614564565b6129175760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610429565b6060613af48484600085613afe565b90505b9392505050565b606082471015613b5f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610429565b843b613bad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610429565b600080866001600160a01b03168587604051613bc99190614637565b60006040518083038185875af1925050503d8060008114613c06576040519150601f19603f3d011682016040523d82523d6000602084013e613c0b565b606091505b5091509150613c1b828286613c26565b979650505050505050565b60608315613c35575081613af7565b825115613c455782518084602001fd5b8160405162461bcd60e51b81526004016104299190614710565b604051806101a00160405280600081526020016000815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b600082601f830112613cd857600080fd5b81356020613ced613ce883614869565b614839565b80838252828201915082860187848660051b8901011115613d0d57600080fd5b60005b85811015613d35578135613d2381614acf565b84529284019290840190600101613d10565b5090979650505050505050565b600082601f830112613d5357600080fd5b81356020613d63613ce883614869565b80838252828201915082860187848660051b8901011115613d8357600080fd5b60005b85811015613d3557613d9782613f5a565b84529284019290840190600101613d86565b600082601f830112613dba57600080fd5b81356020613dca613ce883614869565b80838252828201915082860187848660051b8901011115613dea57600080fd5b6000805b86811015613e1657823560028110613e04578283fd5b85529385019391850191600101613dee565b509198975050505050505050565b600082601f830112613e3557600080fd5b81356020613e45613ce883614869565b80838252828201915082860187848660051b8901011115613e6557600080fd5b6000805b86811015613e1657823560048110613e7f578283fd5b85529385019391850191600101613e69565b600082601f830112613ea257600080fd5b81356020613eb2613ce883614869565b80838252828201915082860187848660051b8901011115613ed257600080fd5b60005b85811015613d3557813584529284019290840190600101613ed5565b600082601f830112613f0257600080fd5b81356020613f12613ce883614869565b80838252828201915082860187848660051b8901011115613f3257600080fd5b60005b85811015613d35578135613f4881614af2565b84529284019290840190600101613f35565b80356001600160e01b031981168114613f7257600080fd5b919050565b600082601f830112613f8857600080fd5b81356001600160401b03811115613fa157613fa1614ab9565b613fb4601f8201601f1916602001614839565b818152846020838601011115613fc957600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613ff857600080fd5b8151613af781614acf565b60006020828403121561401557600080fd5b8135613af781614acf565b600080600080600060a0868803121561403857600080fd5b853561404381614acf565b9450602086013561405381614acf565b935060408601356001600160401b038082111561406f57600080fd5b61407b89838a01613e91565b9450606088013591508082111561409157600080fd5b61409d89838a01613e91565b935060808801359150808211156140b357600080fd5b506140c088828901613f77565b9150509295509295909350565b600080600080608085870312156140e357600080fd5b84356140ee81614acf565b935060208501356140fe81614acf565b92506040850135915060608501356001600160401b0381111561412057600080fd5b61412c87828801613f77565b91505092959194509250565b600080600080600060a0868803121561415057600080fd5b853561415b81614acf565b9450602086013561416b81614acf565b9350604086013592506060860135915060808601356001600160401b0381111561419457600080fd5b6140c088828901613f77565b6000806000606084860312156141b557600080fd5b83356141c081614acf565b95602085013595506040909401359392505050565b600080600080608085870312156141eb57600080fd5b84356001600160401b038082111561420257600080fd5b61420e88838901613da9565b9550602087013591508082111561422457600080fd5b61423088838901613cc7565b9450604087013591508082111561424657600080fd5b61425288838901613e91565b9350606087013591508082111561426857600080fd5b5061412c87828801613e91565b600080600080600060a0868803121561428d57600080fd5b85356001600160401b03808211156142a457600080fd5b6142b089838a01613da9565b965060208801359150808211156142c657600080fd5b6142d289838a01613cc7565b955060408801359150808211156142e857600080fd5b6142f489838a01613e91565b9450606088013591508082111561430a57600080fd5b61431689838a01613e91565b9350608088013591508082111561432c57600080fd5b506140c088828901613e91565b600080600080600080600060e0888a03121561435457600080fd5b87356001600160401b038082111561436b57600080fd5b6143778b838c01613da9565b985060208a013591508082111561438d57600080fd5b6143998b838c01613cc7565b975060408a01359150808211156143af57600080fd5b6143bb8b838c01613e91565b965060608a01359150808211156143d157600080fd5b6143dd8b838c01613e91565b955060808a01359150808211156143f357600080fd5b6143ff8b838c01613ef1565b945060a08a013591508082111561441557600080fd5b6144218b838c01613d42565b935060c08a013591508082111561443757600080fd5b506144448a828b01613e24565b91505092959891949750929550565b60008060008060008060c0878903121561446c57600080fd5b86356001600160401b038082111561448357600080fd5b61448f8a838b01613da9565b975060208901359150808211156144a557600080fd5b6144b18a838b01613cc7565b965060408901359150808211156144c757600080fd5b6144d38a838b01613e91565b955060608901359150808211156144e957600080fd5b6144f58a838b01613e91565b9450608089013591508082111561450b57600080fd5b6145178a838b01613ef1565b935060a089013591508082111561452d57600080fd5b5061453a89828a01613e91565b9150509295509295509295565b60006020828403121561455957600080fd5b8135613af781614ae4565b60006020828403121561457657600080fd5b8151613af781614ae4565b60006020828403121561459357600080fd5b613af782613f5a565b6000602082840312156145ae57600080fd5b5035919050565b6000602082840312156145c757600080fd5b8151613af781614af2565b600081518084526020808501945080840160005b83811015614602578151875295820195908201906001016145e6565b509495945050505050565b60609390931b6bffffffffffffffffffffffff191683526014830191909152603482015260540190565b60008251614649818460208701614a30565b9190910192915050565b6001600160a01b0385811682528416602082015260a06040820181905260009061467f908301856145d2565b828103606084015261469181856145d2565b838103608090940193909352505060008152602001949350505050565b86151581526020810186905260ff851660408201526001600160e01b03198416606082015261ffff8316608082015260c08101600483106146ff57634e487b7160e01b600052602160045260246000fd5b8260a0830152979650505050505050565b602081526000825180602084015261472f816040850160208701614a30565b601f01601f19169190910160400192915050565b6020808252601b908201527f52654e46543a3a696e76616c6964206e6674207374616e646172640000000000604082015260600190565b60208082526017908201527f52654e46543a3a6475726174696f6e206973207a65726f000000000000000000604082015260600190565b60208082526019908201527f52654e46543a3a72656e74207072696365206973207a65726f00000000000000604082015260600190565b6020808252600d908201526c14995391950e8e9c185d5cd959609a1b604082015260600190565b60208082526010908201526f2932a7232a1d1d3737ba1030b236b4b760811b604082015260600190565b604051601f8201601f191681016001600160401b038111828210171561486157614861614ab9565b604052919050565b60006001600160401b0382111561488257614882614ab9565b5060051b60200190565b600061ffff8083168185168083038211156148a9576148a9614a77565b01949350505050565b600082198211156148c5576148c5614a77565b500190565b6000826148e757634e487b7160e01b600052601260045260246000fd5b500490565b600181815b8085111561492757816000190482111561490d5761490d614a77565b8085161561491a57918102915b93841c93908002906148f1565b509250929050565b6000613af7838360008261494557506001610400565b8161495257506000610400565b816001811461496857600281146149725761498e565b6001915050610400565b60ff84111561498357614983614a77565b50506001821b610400565b5060208310610133831016604e8410600b84101617156149b1575081810a610400565b6149bb83836148ec565b80600019048211156149cf576149cf614a77565b029392505050565b60008160001904831182151516156149f1576149f1614a77565b500290565b600061ffff83811690831681811015614a1157614a11614a77565b039392505050565b600082821015614a2b57614a2b614a77565b500390565b60005b83811015614a4b578181015183820152602001614a33565b838111156107085750506000910152565b6000600019821415614a7057614a70614a77565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146115c857600080fd5b80151581146115c857600080fd5b60ff811681146115c857600080fdfea2646970667358221220ec038d9cd55ac9f9fee5cd426853e07e138f4e888a855918789cdbf2dbd5ba3264736f6c63430008070033000000000000000000000000945e589a4715d1915e6fe14f08e4887bc401934100000000000000000000000028f11c3d76169361d22d8ae53551827ac03360b000000000000000000000000000000444e5a1a667663b0adfd853e8efa0470698
Deployed Bytecode
0x6080604052600436106100f35760003560e01c806376774ea31161008a578063c9c4018311610059578063c9c4018314610315578063cbe55e5414610335578063f23a6e6114610348578063fe46b7cd1461037457600080fd5b806376774ea314610285578063937821a1146102a5578063bc197c81146102c5578063bf2b23ea146102f157600080fd5b80631c31f710116100c65780631c31f710146101b35780631cbb410f146101d3578063296c21b7146101f35780635c975abb1461026b57600080fd5b806301ffc9a7146100f857806314b5685c1461012d578063150b7a021461014f57806316c38b3c14610193575b600080fd5b34801561010457600080fd5b50610118610113366004614581565b6103cf565b60405190151581526020015b60405180910390f35b34801561013957600080fd5b5061014d610148366004614275565b610406565b005b34801561015b57600080fd5b5061017a61016a3660046140cd565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610124565b34801561019f57600080fd5b5061014d6101ae366004614547565b610451565b3480156101bf57600080fd5b5061014d6101ce366004614003565b61048e565b3480156101df57600080fd5b5061014d6101ee366004614339565b6104da565b3480156101ff57600080fd5b5061021361020e3660046141a0565b61051b565b6040805160ff98891681526001600160a01b039097166020880152948716948601949094526001600160e01b0319909216606085015261ffff90811660808501521660a08301529190911660c082015260e001610124565b34801561027757600080fd5b506005546101189060ff1681565b34801561029157600080fd5b5061014d6102a036600461459c565b6105f1565b3480156102b157600080fd5b5061014d6102c0366004614275565b610671565b3480156102d157600080fd5b5061017a6102e0366004614020565b63bc197c8160e01b95945050505050565b3480156102fd57600080fd5b5061030760065481565b604051908152602001610124565b34801561032157600080fd5b5061014d6103303660046141d5565b6106a7565b61014d610343366004614453565b61070e565b34801561035457600080fd5b5061017a610363366004614138565b63f23a6e6160e01b95945050505050565b34801561038057600080fd5b5061039461038f3660046141a0565b61074d565b604080516001600160a01b03909516855261ffff909316602085015260ff9091169183019190915263ffffffff166060820152608001610124565b60006001600160e01b03198216630271189760e51b148061040057506301ffc9a760e01b6001600160e01b03198316145b92915050565b60055460ff16156104325760405162461bcd60e51b8152600401610429906147e8565b60405180910390fd5b61044a6107cb6104458787878787610d6d565b610ef3565b5050505050565b6001546001600160a01b0316331461047b5760405162461bcd60e51b81526004016104299061480f565b6005805460ff1916911515919091179055565b6001546001600160a01b031633146104b85760405162461bcd60e51b81526004016104299061480f565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b60055460ff16156104fd5760405162461bcd60e51b8152600401610429906147e8565b610512611028610445898989898989896115cb565b50505050505050565b6000806000806000806000808a8a8a60405160200161053c9392919061460d565b60408051601f19818403018152918152815160209283012060008181526007909352912080549192509060ff16600181111561057a5761057a614a8d565b81546001600160a01b036101008204169060ff600160a81b8204811691600160b01b810460e01b9161ffff600160d01b8304811692600160e01b810490911691600160f01b9091041660038111156105d4576105d4614a8d565b985098509850985098509850985050509397509397509397909450565b6001546001600160a01b0316331461061b5760405162461bcd60e51b81526004016104299061480f565b612710811061066c5760405162461bcd60e51b815260206004820152601960248201527f52654e46543a3a666565206578636565647320313030706374000000000000006044820152606401610429565b600655565b60055460ff16156106945760405162461bcd60e51b8152600401610429906147e8565b61044a6116fb6104458787878787610d6d565b60055460ff16156106ca5760405162461bcd60e51b8152600401610429906147e8565b610708611b02610445868686866000604051908082528060200260200182016040528015610702578160200160208202803683370190505b50610d6d565b50505050565b60055460ff16156107315760405162461bcd60e51b8152600401610429906147e8565b610745611ebb61044588888888888861263c565b505050505050565b600080600080600087878760405160200161076a9392919061460d565b60408051808303601f190181529181528151602092830120600090815260089092529020546001600160a01b03811699600160c81b820461ffff169950600160a01b820460ff169850600160a81b90910463ffffffff169650945050505050565b80515b8160200151811015610d6957600082606001518360000151815181106107f6576107f6614aa3565b60200260200101518360800151838151811061081457610814614aa3565b6020026020010151846101000151848151811061083357610833614aa3565b602002602001015160405160200161084d9392919061460d565b6040516020818303038152906040528051906020012090506000836060015184600001518151811061088157610881614aa3565b60200260200101518460800151848151811061089f5761089f614aa3565b602002602001015185610120015185815181106108be576108be614aa3565b60200260200101516040516020016108d89392919061460d565b60408051601f198184030181528282528051602091820120600086815260078352838120828252600890935283902060e08501909352815490945090926109d9918490829060ff16600181111561093157610931614a8d565b600181111561094257610942614a8d565b815281546001600160a01b03610100820416602083015260ff600160a81b8204811660408401526001600160e01b0319600160b01b830460e01b16606084015261ffff600160d01b830481166080850152600160e01b83041660a084015260c090920191600160f01b9091041660038111156109c0576109c0614a8d565b60038111156109d1576109d1614a8d565b90525061275e565b6040805160808101825282546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff166060820152610a2e906127e1565b6040805160808101825282546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff166060820152610a85903342612867565b815460ff166001811115610a9b57610a9b614a8d565b86604001518681518110610ab157610ab1614aa3565b60200260200101516001811115610aca57610aca614a8d565b14610ae75760405162461bcd60e51b815260040161042990614743565b81548154600160d01b90910461ffff908116600160c81b909204161115610b485760405162461bcd60e51b81526020600482015260156024820152742932a7232a1d1d31b934ba34b1b0b61032b93937b960591b6044820152606401610429565b8054600090610b6490600160a81b900463ffffffff1642614a19565b6040805160e081019091528454919250610c85918590829060ff166001811115610b9057610b90614a8d565b6001811115610ba157610ba1614a8d565b815281546001600160a01b03610100820416602083015260ff600160a81b8204811660408401526001600160e01b0319600160b01b830460e01b16606084015261ffff600160d01b830481166080850152600160e01b83041660a084015260c090920191600160f01b909104166003811115610c1f57610c1f614a8d565b6003811115610c3057610c30614a8d565b9052506040805160808101825285546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff1660608201528361291c565b81546000868152600760205260409020805461ffff600160c81b909304831692601c91610cbb918591600160e01b90041661488c565b92506101000a81548161ffff021916908361ffff1602179055508661012001518681518110610cec57610cec614aa3565b60200260200101517f58855dd8908b14c6d7922d964418f37efd968bc6b9b857560870b14a898f916d42604051610d2f919063ffffffff91909116815260200190565b60405180910390a2505050600090815260086020526040902080546001600160d81b03191690555080610d6181614a5c565b9150506107ce565b5050565b610d75613c5f565b604051806101a00160405280600081526020016001815260200187815260200186815260200185815260200160006001600160401b03811115610dba57610dba614ab9565b604051908082528060200260200182016040528015610de3578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610e14578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610e45578160200160208202803683370190505b50815260208101859052604081018490526060016000604051908082528060200260200182016040528015610e84578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610eb5578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610ee6578160200160208202803683370190505b5090529695505050505050565b600081606001515111610f395760405162461bcd60e51b815260206004820152600e60248201526d52654e46543a3a6e6f206e66747360901b6044820152606401610429565b80606001515181602001511461101b578060600151816020015181518110610f6357610f63614aa3565b60200260200101516001600160a01b03168160600151826000015181518110610f8e57610f8e614aa3565b60200260200101516001600160a01b0316148015610fde575060018160400151826020015181518110610fc357610fc3614aa3565b60200260200101516001811115610fdc57610fdc614a8d565b145b15610ffb5760208101805190610ff382614a5c565b905250610f39565b611008818363ffffffff16565b60208101805180835290610ff382614a5c565b610d69818363ffffffff16565b80515b816020015181101561158a576110418282612bc1565b6000826060015183600001518151811061105d5761105d614aa3565b60200260200101518360800151838151811061107b5761107b614aa3565b60200260200101516003546040516020016110989392919061460d565b60408051601f198184030181528282528051602091820120600081815260079092529082902060e0840190925281549093509091611190918390829060ff1660018111156110e8576110e8614a8d565b60018111156110f9576110f9614a8d565b815281546001600160a01b03610100820416602083015260ff600160a81b8204811660408401526001600160e01b0319600160b01b830460e01b16606084015261ffff600160d01b830481166080850152600160e01b83041660a084015260c090920191600160f01b90910416600381111561117757611177614a8d565b600381111561118857611188614a8d565b905250612d7f565b6111c884610180015184815181106111aa576111aa614aa3565b602002602001015160038111156111c3576111c3614a8d565b612e38565b600080856040015185815181106111e1576111e1614aa3565b602002602001015160018111156111fa576111fa614a8d565b1490506040518060e001604052808660400151868151811061121e5761121e614aa3565b6020026020010151600181111561123757611237614a8d565b8152602001336001600160a01b031681526020018660c00151868151811061126157611261614aa3565b602002602001015160ff1681526020018660e00151868151811061128757611287614aa3565b60200260200101516001600160e01b0319168152602001826112c6578660a0015186815181106112b9576112b9614aa3565b60200260200101516112c9565b60015b61ffff168152602001826112fa578660a0015186815181106112ed576112ed614aa3565b60200260200101516112fd565b60015b61ffff168152602001866101800151868151811061131d5761131d614aa3565b6020026020010151600381111561133657611336614a8d565b9052600084815260076020526040902081518154829060ff19166001838181111561136357611363614a8d565b02179055506020820151815460408401516060850151608086015160a0870151610100600160b01b03199094166101006001600160a01b039096169590950260ff60a81b191694909417600160a81b60ff909316929092029190911765ffffffffffff60b01b1916600160b01b60e09290921c9190910261ffff60d01b191617600160d01b61ffff938416021761ffff60e01b198116600160e01b9390921692909202908117835560c084015191839162ffffff60e01b1990911660ff60f01b1990911617600160f01b83600381111561143f5761143f614a8d565b02179055509050508460800151848151811061145d5761145d614aa3565b6020026020010151856060015186600001518151811061147f5761147f614aa3565b60200260200101516001600160a01b0316336001600160a01b03167f46e173c7568bb4f093e16923381dcba2a6b48f9cc9e688867965731218500ad3846003548a60c001518a815181106114d5576114d5614aa3565b60200260200101518b60e001518b815181106114f3576114f3614aa3565b602002602001015188611523578c60a001518c8151811061151657611516614aa3565b6020026020010151611526565b60015b8d61018001518d8151811061153d5761153d614aa3565b6020026020010151604051611557969594939291906146ae565b60405180910390a46003805490600061156f83614a5c565b9190505550505050808061158290614a5c565b91505061102b565b506115c88133306115aa8560800151866000015187602001516000612e8b565b6115c38660a00151876000015188602001516000612e8b565b612f4a565b50565b6115d3613c5f565b604051806101a00160405280600081526020016001815260200189815260200188815260200187815260200186815260200185815260200184815260200160006001600160401b0381111561162a5761162a614ab9565b604051908082528060200260200182016040528015611653578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015611684578160200160208202803683370190505b50815260200160006040519080825280602002602001820160405280156116b5578160200160208202803683370190505b50815260200160006040519080825280602002602001820160405280156116e6578160200160208202803683370190505b50815260200192909252509695505050505050565b80515b8160200151811015610d69576000826060015183600001518151811061172657611726614aa3565b60200260200101518360800151838151811061174457611744614aa3565b6020026020010151846101000151848151811061176357611763614aa3565b602002602001015160405160200161177d9392919061460d565b604051602081830303815290604052805190602001209050600083606001518460000151815181106117b1576117b1614aa3565b6020026020010151846080015184815181106117cf576117cf614aa3565b602002602001015185610120015185815181106117ee576117ee614aa3565b60200260200101516040516020016118089392919061460d565b60408051601f198184030181528282528051602091820120600086815260078352838120828252600890935283902060e0850190935281549094509092611861918490829060ff16600181111561093157610931614a8d565b6040805160808101825282546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff1660608201526118b6906127e1565b6040805160808101825282546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff16606082015261190c90426130cb565b6040805160e081019091528254611a2a91908490829060ff16600181111561193657611936614a8d565b600181111561194757611947614a8d565b815281546001600160a01b03610100820416602083015260ff600160a81b8204811660408401526001600160e01b0319600160b01b830460e01b16606084015261ffff600160d01b830481166080850152600160e01b83041660a084015260c090920191600160f01b9091041660038111156119c5576119c5614a8d565b60038111156119d6576119d6614a8d565b9052506040805160808101825284546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff166060820152613121565b8054825461ffff600160c81b9092048216918491601c91611a55918591600160e01b9091041661488c565b92506101000a81548161ffff021916908361ffff1602179055508561012001518581518110611a8657611a86614aa3565b60200260200101517f4630b53a4335803b2a4f9c1ce896f4cadbf909907810e496eda17614483d7b9442604051611ac9919063ffffffff91909116815260200190565b60405180910390a25050600090815260086020526040902080546001600160d81b03191690555080611afa81614a5c565b9150506116fe565b80516020820151600091611b1591614a19565b6001600160401b03811115611b2c57611b2c614ab9565b604051908082528060200260200182016040528015611b55578160200160208202803683370190505b5082519091505b8260200151811015611e885760008360600151846000015181518110611b8457611b84614aa3565b602002602001015184608001518381518110611ba257611ba2614aa3565b60200260200101518561010001518481518110611bc157611bc1614aa3565b6020026020010151604051602001611bdb9392919061460d565b60408051601f198184030181528282528051602091820120600081815260079092529082902060e0840190925281549093509091611c2b918390829060ff16600181111561093157610931614a8d565b6040805160e081019091528154611cfe91908390829060ff166001811115611c5557611c55614a8d565b6001811115611c6657611c66614a8d565b815281546001600160a01b03610100820416602083015260ff600160a81b8204811660408401526001600160e01b0319600160b01b830460e01b16606084015261ffff600160d01b830481166080850152600160e01b83041660a084015260c090920191600160f01b909104166003811115611ce457611ce4614a8d565b6003811115611cf557611cf5614a8d565b905250336132d3565b805460ff166001811115611d1457611d14614a8d565b85604001518481518110611d2a57611d2a614aa3565b60200260200101516001811115611d4357611d43614a8d565b14611d605760405162461bcd60e51b815260040161042990614743565b8054600160d01b810461ffff908116600160e01b9092041614611dbe5760405162461bcd60e51b815260206004820152601660248201527514995391950e8e9858dd1a5d995b1e481c995b9d195960521b6044820152606401610429565b80548551600160d01b90910461ffff16908590611ddb9086614a19565b81518110611deb57611deb614aa3565b6020026020010181815250508461010001518381518110611e0e57611e0e614aa3565b60200260200101517fd0234bc8dd7e933f60cbc1e90fc139a8a9683af1cb92743607dafb9dfb70059b42604051611e51919063ffffffff91909116815260200190565b60405180910390a250600090815260076020526040902080546001600160f81b031916905580611e8081614a5c565b915050611b5c565b50610d69823033611ea88660800151876000015188602001516000612e8b565b865160208801516115c391889181612e8b565b80515b8160200151811015610d695760008260600151836000015181518110611ee657611ee6614aa3565b602002602001015183608001518381518110611f0457611f04614aa3565b60200260200101518461010001518481518110611f2357611f23614aa3565b6020026020010151604051602001611f3d9392919061460d565b60405160208183030381529060405280519060200120905060008360600151846000015181518110611f7157611f71614aa3565b602002602001015184608001518481518110611f8f57611f8f614aa3565b6020026020010151600454604051602001611fac9392919061460d565b60408051601f198184030181528282528051602091820120600086815260078352838120828252600890935283902060e0850190935281549094509092612005918490829060ff16600181111561093157610931614a8d565b6040805160808101825282546001600160a01b0381168252600160a01b810460ff166020830152600160a81b810463ffffffff1692820192909252600160c81b90910461ffff16606082015261205a9061332c565b6040805160e08101909152825461212f91908490829060ff16600181111561208457612084614a8d565b600181111561209557612095614a8d565b815281546001600160a01b03610100820416602083015260ff600160a81b8204811660408401526001600160e01b0319600160b01b830460e01b16606084015261ffff600160d01b830481166080850152600160e01b83041660a084015260c090920191600160f01b90910416600381111561211357612113614a8d565b600381111561212457612124614a8d565b9052508787336133df565b815460ff16600181111561214557612145614a8d565b8660400151868151811061215b5761215b614aa3565b6020026020010151600181111561217457612174614a8d565b146121915760405162461bcd60e51b815260040161042990614743565b81546101608701518051600160e01b90920461ffff1691879081106121b8576121b8614aa3565b6020026020010151111561220e5760405162461bcd60e51b815260206004820152601a60248201527f52654e46543a3a696e76616c69642072656e7420616d6f756e740000000000006044820152606401610429565b8154600090600160f01b900460ff16600381111561222e5761222e614a8d565b6000805460405163c6ee427f60e01b815260ff8416600482015292935090916001600160a01b039091169063c6ee427f9060240160206040518083038186803b15801561227a57600080fd5b505afa15801561228e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b29190613fe6565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156122ef57600080fd5b505afa158015612303573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232791906145b5565b60ff169050600061233982600a61492f565b865490915060009061235590600160b01b900460e01b8361364a565b8b61014001518b8151811061236c5761236c614aa3565b602002602001015160ff168c61016001518c8151811061238e5761238e614aa3565b60200260200101516123a091906149d7565b6123aa91906149d7565b9050600081116123cc5760405162461bcd60e51b8152600401610429906147b1565b6123e16001600160a01b0385163330846136d9565b50506040518060800160405280336001600160a01b031681526020018a61014001518a8151811061241457612414614aa3565b602002602001015160ff1681526020014263ffffffff1681526020018a61016001518a8151811061244757612447614aa3565b60209081029190910181015161ffff908116909252600089815260088252604090819020845181549386015192860151606090960151909416600160c81b0261ffff60c81b1963ffffffff909616600160a81b029590951665ffffffffffff60a81b1960ff909316600160a01b026001600160a81b03199094166001600160a01b03909516949094179290921716919091179190911790556101608901518051899081106124f7576124f7614aa3565b6020908102919091018101516000898152600790925260409091208054601c9061252d908490600160e01b900461ffff166149f6565b92506101000a81548161ffff021916908361ffff160217905550600454896101000151898151811061256157612561614aa3565b6020026020010151336001600160a01b03167f61e1a1e6f89eaba4ba0119b0023bd32b1bb0412ab96ccd8d0588a3e98a0976318c61016001518c815181106125ab576125ab614aa3565b60200260200101518d61014001518d815181106125ca576125ca614aa3565b6020908102919091018101518a546040805161ffff909516855260ff90921692840192909252600160a81b90910463ffffffff169082015260600160405180910390a46004805490600061261d83614a5c565b919050555050505050505050808061263490614a5c565b915050611ebe565b612644613c5f565b604051806101a00160405280600081526020016001815260200188815260200187815260200186815260200160006001600160401b0381111561268957612689614ab9565b6040519080825280602002602001820160405280156126b2578160200160208202803683370190505b50815260200160006040519080825280602002602001820160405280156126e3578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015612714578160200160208202803683370190505b5081526020808201969096526040805160008082528189018352828401919091526060830196909652608082019490945283519485529484019092525060a0909201529392505050565b61276b8160200151613744565b604081015160ff166127b65760405162461bcd60e51b815260206004820152601460248201527352654e46543a3a6475726174696f6e207a65726f60601b6044820152606401610429565b60608101516001600160e01b0319166115c85760405162461bcd60e51b8152600401610429906147b1565b80516127ec90613744565b602081015160ff166128105760405162461bcd60e51b81526004016104299061477a565b604081015163ffffffff166115c85760405162461bcd60e51b815260206004820152601860248201527f52654e46543a3a72656e746564206174206973207a65726f00000000000000006044820152606401610429565b816001600160a01b031683600001516001600160a01b0316146128c05760405162461bcd60e51b81526020600482015260116024820152702932a7232a1d1d3737ba103932b73a32b960791b6044820152606401610429565b6128ca8382613790565b156129175760405162461bcd60e51b815260206004820152601760248201527f52654e46543a3a706173742072657475726e20646174650000000000000000006044820152606401610429565b505050565b60008360c00151600381111561293457612934614a8d565b6000805460405163c6ee427f60e01b815260ff8416600482015292935090916001600160a01b039091169063c6ee427f9060240160206040518083038186803b15801561298057600080fd5b505afa158015612994573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b89190613fe6565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156129f557600080fd5b505afa158015612a09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2d91906145b5565b60ff1690506000612a3f82600a61492f565b90506000612a5188606001518361364a565b876060015161ffff16612a6491906149d7565b90506000876020015160ff1682612a7b91906149d7565b9050600062015180612a8d848a6149d7565b612a9791906148ca565b905060008211612af55760405162461bcd60e51b815260206004820152602360248201527f52654e46543a3a746f74616c2072656e746572207061796d656e74206973207a60448201526265726f60e81b6064820152608401610429565b60008111612b455760405162461bcd60e51b815260206004820152601d60248201527f52654e46543a3a6c656e646572207061796d656e74206973207a65726f0000006044820152606401610429565b6000612b518284614a19565b9050600654600014612b7d576000612b6d838d60c0015161381e565b9050612b798184614a19565b9250505b60208b0151612b97906001600160a01b03891690846138fb565b8015612bb4578951612bb4906001600160a01b03891690836138fb565b5050505050505050505050565b60008260a001518281518110612bd957612bd9614aa3565b602002602001015111612c2e5760405162461bcd60e51b815260206004820152601a60248201527f52654e46543a3a6c656e6420616d6f756e74206973207a65726f0000000000006044820152606401610429565b61ffff80168260a001518281518110612c4957612c49614aa3565b60200260200101511115612c935760405162461bcd60e51b81526020600482015260116024820152702932a7232a1d1d3737ba103ab4b73a189b60791b6044820152606401610429565b60008260c001518281518110612cab57612cab614aa3565b602002602001015160ff1611612cd35760405162461bcd60e51b81526004016104299061477a565b60ff80168260c001518281518110612ced57612ced614aa3565b602002602001015160ff161115612d395760405162461bcd60e51b815260206004820152601060248201526f0a4ca9c8ca87474dcdee840ead2dce8760831b6044820152606401610429565b60008260e001518281518110612d5157612d51614aa3565b602002602001015160e01c63ffffffff1611610d695760405162461bcd60e51b8152600401610429906147b1565b612d8c816020015161392b565b604081015160ff1615612ddc5760405162461bcd60e51b815260206004820152601860248201527752654e46543a3a6475726174696f6e206e6f74207a65726f60401b6044820152606401610429565b60608101516001600160e01b031916156115c85760405162461bcd60e51b815260206004820152601a60248201527f52654e46543a3a72656e74207072696365206e6f74207a65726f0000000000006044820152606401610429565b60008160ff16116115c85760405162461bcd60e51b815260206004820152601860248201527f52654e46543a3a746f6b656e2069732073656e74696e656c00000000000000006044820152606401610429565b6060612e978484614a19565b6001600160401b03811115612eae57612eae614ab9565b604051908082528060200260200182016040528015612ed7578160200160208202803683370190505b509050835b83811015612f415785612eef8483614a19565b81518110612eff57612eff614aa3565b6020026020010151828683612f149190614a19565b81518110612f2457612f24614aa3565b602090810291909101015280612f3981614a5c565b915050612edc565b50949350505050565b60006040860151865181518110612f6357612f63614aa3565b60200260200101516001811115612f7c57612f7c614a8d565b1415613042576060850151855181518110612f9957612f99614aa3565b60200260200101516001600160a01b03166323b872dd85858860800151896000015181518110612fcb57612fcb614aa3565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561302557600080fd5b505af1158015613039573d6000803e3d6000fd5b5050505061044a565b606085015185518151811061305957613059614aa3565b60200260200101516001600160a01b0316632eb2c2d6858585856040518563ffffffff1660e01b81526004016130929493929190614653565b600060405180830381600087803b1580156130ac57600080fd5b505af11580156130c0573d6000803e3d6000fd5b505050505050505050565b6130d58282613790565b610d695760405162461bcd60e51b815260206004820152601d60248201527f52654e46543a3a72657475726e2064617465206e6f74207061737365640000006044820152606401610429565b60008260c00151600381111561313957613139614a8d565b6000805460405163c6ee427f60e01b815260ff8416600482015292935090916001600160a01b039091169063c6ee427f9060240160206040518083038186803b15801561318557600080fd5b505afa158015613199573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131bd9190613fe6565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156131fa57600080fd5b505afa15801561320e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061323291906145b5565b60ff169050600061324482600a61492f565b9050600061325687606001518361364a565b866060015161ffff1661326991906149d7565b90506000866020015160ff168261328091906149d7565b905060006006546000146132af576132ac828860ff1660038111156132a7576132a7614a8d565b61381e565b90505b60208901516130c0906132c28385614a19565b6001600160a01b03891691906138fb565b806001600160a01b031682602001516001600160a01b031614610d695760405162461bcd60e51b81526020600482015260116024820152702932a7232a1d1d3737ba103632b73232b960791b6044820152606401610429565b80516133379061392b565b602081015160ff16156133875760405162461bcd60e51b815260206004820152601860248201527752654e46543a3a6475726174696f6e206e6f74207a65726f60401b6044820152606401610429565b604081015163ffffffff16156115c85760405162461bcd60e51b815260206004820152601960248201527f52654e46543a3a72656e746564206174206e6f74207a65726f000000000000006044820152606401610429565b83602001516001600160a01b0316816001600160a01b031614156134455760405162461bcd60e51b815260206004820152601860248201527f52654e46543a3a63616e742072656e74206f776e206e667400000000000000006044820152606401610429565b60ff8016836101400151838151811061346057613460614aa3565b602002602001015160ff1611156134ac5760405162461bcd60e51b815260206004820152601060248201526f0a4ca9c8ca87474dcdee840ead2dce8760831b6044820152606401610429565b600083610140015183815181106134c5576134c5614aa3565b602002602001015160ff16116134ed5760405162461bcd60e51b81526004016104299061477a565b61ffff8016836101600151838151811061350957613509614aa3565b602002602001015111156135535760405162461bcd60e51b81526020600482015260116024820152702932a7232a1d1d3737ba103ab4b73a189b60791b6044820152606401610429565b6000836101600151838151811061356c5761356c614aa3565b6020026020010151116135c15760405162461bcd60e51b815260206004820152601960248201527f52654e46543a3a72656e74416d6f756e74206973207a65726f000000000000006044820152606401610429565b836040015160ff1683610140015183815181106135e0576135e0614aa3565b602002602001015160ff1611156107085760405162461bcd60e51b815260206004820152602860248201527f52654e46543a3a72656e74206475726174696f6e206578636565647320616c6c6044820152670deeecac840dac2f60c31b6064820152608401610429565b60006136568383613982565b60f083901c61ffff60e085901c166000613672612710866148ca565b905061270f8361ffff1611156136885761270f92505b61270f8261ffff16111561369c5761270f91505b60006136ac8661ffff86166149d7565b905060006136be8361ffff86166149d7565b905060006136cc82846148b2565b9998505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526107089085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613a13565b6001600160a01b0381166115c85760405162461bcd60e51b815260206004820152601360248201527252654e46543a3a7a65726f206164647265737360681b6044820152606401610429565b6000826040015163ffffffff1682116137eb5760405162461bcd60e51b815260206004820152601860248201527f52654e46543a3a6e6f77206265666f72652072656e74656400000000000000006044820152606401610429565b62015180836020015160ff1661380191906149d7565b60408401516138169063ffffffff1684614a19565b119392505050565b60006006548361382e91906149d7565b905061383c612710826148ca565b9050600082600381111561385257613852614a8d565b6000805460405163c6ee427f60e01b815260ff8416600482015292935090916001600160a01b039091169063c6ee427f9060240160206040518083038186803b15801561389e57600080fd5b505afa1580156138b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138d69190613fe6565b6002549091506138f3906001600160a01b038084169116856138fb565b505092915050565b6040516001600160a01b03831660248201526044810182905261291790849063a9059cbb60e01b9060640161370d565b6001600160a01b038116156115c85760405162461bcd60e51b815260206004820152601960248201527f52654e46543a3a6e6f742061207a65726f2061646472657373000000000000006044820152606401610429565b60e082901c6139ca5760405162461bcd60e51b815260206004820152601460248201527352654e46543a3a696e76616c696420707269636560601b6044820152606401610429565b612710811015610d695760405162461bcd60e51b815260206004820152601460248201527352654e46543a3a696e76616c6964207363616c6560601b6044820152606401610429565b6000613a68826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613ae59092919063ffffffff16565b8051909150156129175780806020019051810190613a869190614564565b6129175760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610429565b6060613af48484600085613afe565b90505b9392505050565b606082471015613b5f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610429565b843b613bad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610429565b600080866001600160a01b03168587604051613bc99190614637565b60006040518083038185875af1925050503d8060008114613c06576040519150601f19603f3d011682016040523d82523d6000602084013e613c0b565b606091505b5091509150613c1b828286613c26565b979650505050505050565b60608315613c35575081613af7565b825115613c455782518084602001fd5b8160405162461bcd60e51b81526004016104299190614710565b604051806101a00160405280600081526020016000815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b600082601f830112613cd857600080fd5b81356020613ced613ce883614869565b614839565b80838252828201915082860187848660051b8901011115613d0d57600080fd5b60005b85811015613d35578135613d2381614acf565b84529284019290840190600101613d10565b5090979650505050505050565b600082601f830112613d5357600080fd5b81356020613d63613ce883614869565b80838252828201915082860187848660051b8901011115613d8357600080fd5b60005b85811015613d3557613d9782613f5a565b84529284019290840190600101613d86565b600082601f830112613dba57600080fd5b81356020613dca613ce883614869565b80838252828201915082860187848660051b8901011115613dea57600080fd5b6000805b86811015613e1657823560028110613e04578283fd5b85529385019391850191600101613dee565b509198975050505050505050565b600082601f830112613e3557600080fd5b81356020613e45613ce883614869565b80838252828201915082860187848660051b8901011115613e6557600080fd5b6000805b86811015613e1657823560048110613e7f578283fd5b85529385019391850191600101613e69565b600082601f830112613ea257600080fd5b81356020613eb2613ce883614869565b80838252828201915082860187848660051b8901011115613ed257600080fd5b60005b85811015613d3557813584529284019290840190600101613ed5565b600082601f830112613f0257600080fd5b81356020613f12613ce883614869565b80838252828201915082860187848660051b8901011115613f3257600080fd5b60005b85811015613d35578135613f4881614af2565b84529284019290840190600101613f35565b80356001600160e01b031981168114613f7257600080fd5b919050565b600082601f830112613f8857600080fd5b81356001600160401b03811115613fa157613fa1614ab9565b613fb4601f8201601f1916602001614839565b818152846020838601011115613fc957600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613ff857600080fd5b8151613af781614acf565b60006020828403121561401557600080fd5b8135613af781614acf565b600080600080600060a0868803121561403857600080fd5b853561404381614acf565b9450602086013561405381614acf565b935060408601356001600160401b038082111561406f57600080fd5b61407b89838a01613e91565b9450606088013591508082111561409157600080fd5b61409d89838a01613e91565b935060808801359150808211156140b357600080fd5b506140c088828901613f77565b9150509295509295909350565b600080600080608085870312156140e357600080fd5b84356140ee81614acf565b935060208501356140fe81614acf565b92506040850135915060608501356001600160401b0381111561412057600080fd5b61412c87828801613f77565b91505092959194509250565b600080600080600060a0868803121561415057600080fd5b853561415b81614acf565b9450602086013561416b81614acf565b9350604086013592506060860135915060808601356001600160401b0381111561419457600080fd5b6140c088828901613f77565b6000806000606084860312156141b557600080fd5b83356141c081614acf565b95602085013595506040909401359392505050565b600080600080608085870312156141eb57600080fd5b84356001600160401b038082111561420257600080fd5b61420e88838901613da9565b9550602087013591508082111561422457600080fd5b61423088838901613cc7565b9450604087013591508082111561424657600080fd5b61425288838901613e91565b9350606087013591508082111561426857600080fd5b5061412c87828801613e91565b600080600080600060a0868803121561428d57600080fd5b85356001600160401b03808211156142a457600080fd5b6142b089838a01613da9565b965060208801359150808211156142c657600080fd5b6142d289838a01613cc7565b955060408801359150808211156142e857600080fd5b6142f489838a01613e91565b9450606088013591508082111561430a57600080fd5b61431689838a01613e91565b9350608088013591508082111561432c57600080fd5b506140c088828901613e91565b600080600080600080600060e0888a03121561435457600080fd5b87356001600160401b038082111561436b57600080fd5b6143778b838c01613da9565b985060208a013591508082111561438d57600080fd5b6143998b838c01613cc7565b975060408a01359150808211156143af57600080fd5b6143bb8b838c01613e91565b965060608a01359150808211156143d157600080fd5b6143dd8b838c01613e91565b955060808a01359150808211156143f357600080fd5b6143ff8b838c01613ef1565b945060a08a013591508082111561441557600080fd5b6144218b838c01613d42565b935060c08a013591508082111561443757600080fd5b506144448a828b01613e24565b91505092959891949750929550565b60008060008060008060c0878903121561446c57600080fd5b86356001600160401b038082111561448357600080fd5b61448f8a838b01613da9565b975060208901359150808211156144a557600080fd5b6144b18a838b01613cc7565b965060408901359150808211156144c757600080fd5b6144d38a838b01613e91565b955060608901359150808211156144e957600080fd5b6144f58a838b01613e91565b9450608089013591508082111561450b57600080fd5b6145178a838b01613ef1565b935060a089013591508082111561452d57600080fd5b5061453a89828a01613e91565b9150509295509295509295565b60006020828403121561455957600080fd5b8135613af781614ae4565b60006020828403121561457657600080fd5b8151613af781614ae4565b60006020828403121561459357600080fd5b613af782613f5a565b6000602082840312156145ae57600080fd5b5035919050565b6000602082840312156145c757600080fd5b8151613af781614af2565b600081518084526020808501945080840160005b83811015614602578151875295820195908201906001016145e6565b509495945050505050565b60609390931b6bffffffffffffffffffffffff191683526014830191909152603482015260540190565b60008251614649818460208701614a30565b9190910192915050565b6001600160a01b0385811682528416602082015260a06040820181905260009061467f908301856145d2565b828103606084015261469181856145d2565b838103608090940193909352505060008152602001949350505050565b86151581526020810186905260ff851660408201526001600160e01b03198416606082015261ffff8316608082015260c08101600483106146ff57634e487b7160e01b600052602160045260246000fd5b8260a0830152979650505050505050565b602081526000825180602084015261472f816040850160208701614a30565b601f01601f19169190910160400192915050565b6020808252601b908201527f52654e46543a3a696e76616c6964206e6674207374616e646172640000000000604082015260600190565b60208082526017908201527f52654e46543a3a6475726174696f6e206973207a65726f000000000000000000604082015260600190565b60208082526019908201527f52654e46543a3a72656e74207072696365206973207a65726f00000000000000604082015260600190565b6020808252600d908201526c14995391950e8e9c185d5cd959609a1b604082015260600190565b60208082526010908201526f2932a7232a1d1d3737ba1030b236b4b760811b604082015260600190565b604051601f8201601f191681016001600160401b038111828210171561486157614861614ab9565b604052919050565b60006001600160401b0382111561488257614882614ab9565b5060051b60200190565b600061ffff8083168185168083038211156148a9576148a9614a77565b01949350505050565b600082198211156148c5576148c5614a77565b500190565b6000826148e757634e487b7160e01b600052601260045260246000fd5b500490565b600181815b8085111561492757816000190482111561490d5761490d614a77565b8085161561491a57918102915b93841c93908002906148f1565b509250929050565b6000613af7838360008261494557506001610400565b8161495257506000610400565b816001811461496857600281146149725761498e565b6001915050610400565b60ff84111561498357614983614a77565b50506001821b610400565b5060208310610133831016604e8410600b84101617156149b1575081810a610400565b6149bb83836148ec565b80600019048211156149cf576149cf614a77565b029392505050565b60008160001904831182151516156149f1576149f1614a77565b500290565b600061ffff83811690831681811015614a1157614a11614a77565b039392505050565b600082821015614a2b57614a2b614a77565b500390565b60005b83811015614a4b578181015183820152602001614a33565b838111156107085750506000910152565b6000600019821415614a7057614a70614a77565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146115c857600080fd5b80151581146115c857600080fd5b60ff811681146115c857600080fdfea2646970667358221220ec038d9cd55ac9f9fee5cd426853e07e138f4e888a855918789cdbf2dbd5ba3264736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000945e589a4715d1915e6fe14f08e4887bc401934100000000000000000000000028f11c3d76169361d22d8ae53551827ac03360b000000000000000000000000000000444e5a1a667663b0adfd853e8efa0470698
-----Decoded View---------------
Arg [0] : newResolver (address): 0x945E589A4715d1915e6FE14f08e4887Bc4019341
Arg [1] : newBeneficiary (address): 0x28f11c3D76169361D22D8aE53551827Ac03360B0
Arg [2] : newAdmin (address): 0x00000444e5a1a667663b0ADfD853E8Efa0470698
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000945e589a4715d1915e6fe14f08e4887bc4019341
Arg [1] : 00000000000000000000000028f11c3d76169361d22d8ae53551827ac03360b0
Arg [2] : 00000000000000000000000000000444e5a1a667663b0adfd853e8efa0470698
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.