Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 2,927 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Safe Transfer Fr... | 44074211 | 15 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 44074155 | 15 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 44074025 | 15 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 44074015 | 15 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 44073981 | 15 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 44073070 | 15 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 44073063 | 15 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 44066253 | 15 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 42896237 | 85 days ago | IN | 0 XDAI | 0.00000034 | ||||
| Safe Transfer Fr... | 42235845 | 125 days ago | IN | 0 XDAI | 0.00000011 | ||||
| Safe Transfer Fr... | 41335855 | 178 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41335852 | 178 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41335847 | 178 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41302831 | 180 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41302829 | 180 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41302827 | 180 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41302827 | 180 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41302816 | 180 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41285267 | 181 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41282397 | 182 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41282395 | 182 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41282393 | 182 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41282392 | 182 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41282391 | 182 days ago | IN | 0 XDAI | 0 | ||||
| Safe Transfer Fr... | 41269196 | 182 days ago | IN | 0 XDAI | 0 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 43566866 | 45 days ago | Contract Creation | 0 XDAI | |||
| 37475939 | 408 days ago | Contract Creation | 0 XDAI | |||
| 35830218 | 506 days ago | Contract Creation | 0 XDAI | |||
| 35796485 | 508 days ago | 0.98039215 XDAI | ||||
| 35796485 | 508 days ago | Contract Creation | 0 XDAI | |||
| 35158653 | 547 days ago | 0.98039215 XDAI | ||||
| 35158653 | 547 days ago | Contract Creation | 0 XDAI | |||
| 35144748 | 548 days ago | Contract Creation | 0 XDAI | |||
| 33868861 | 624 days ago | 0.98039215 XDAI | ||||
| 33868861 | 624 days ago | Contract Creation | 0 XDAI | |||
| 33560451 | 642 days ago | Contract Creation | 0 XDAI | |||
| 33472496 | 648 days ago | Contract Creation | 0 XDAI | |||
| 32417270 | 711 days ago | Contract Creation | 0 XDAI | |||
| 31846516 | 746 days ago | 0.98039215 XDAI | ||||
| 31846516 | 746 days ago | Contract Creation | 0 XDAI | |||
| 31209380 | 785 days ago | 0.98039215 XDAI | ||||
| 31209380 | 785 days ago | Contract Creation | 0 XDAI | |||
| 31147333 | 789 days ago | Contract Creation | 0 XDAI | |||
| 31049608 | 795 days ago | Contract Creation | 0 XDAI | |||
| 31049595 | 795 days ago | Contract Creation | 0 XDAI | |||
| 31049577 | 795 days ago | Contract Creation | 0 XDAI | |||
| 31049555 | 795 days ago | Contract Creation | 0 XDAI | |||
| 31049539 | 795 days ago | Contract Creation | 0 XDAI | |||
| 31049501 | 795 days ago | Contract Creation | 0 XDAI | |||
| 31048878 | 795 days ago | Contract Creation | 0 XDAI |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Collections
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/**
*Submitted for verification at gnosisscan.io on 2022-08-04
*/
/*
* Crypto stamp Collections Factory (Layer 2)
* Factory and core ERC721 contract for the Collections of ERC721 and ERC1155 assets,
* for example digital-physical collectible postage stamps
*
* Developed by Capacity Blockchain Solutions GmbH <capacity.at>
* for Österreichische Post AG <post.at>
*
* Any usage of or interaction with this set of contracts is subject to the
* Terms & Conditions available at https://crypto.post.at/
*/
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol
/**
* @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);
}
// File: @openzeppelin/contracts/utils/introspection/IERC165.sol
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File: @openzeppelin/contracts/token/ERC721/IERC721.sol
/**
* @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;
}
// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol
/**
* @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);
}
// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}
// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}
// File: @openzeppelin/contracts/utils/Address.sol
/**
* @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;
// solhint-disable-next-line no-inline-assembly
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");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(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");
// solhint-disable-next-line avoid-low-level-calls
(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");
// solhint-disable-next-line avoid-low-level-calls
(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");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// File: @openzeppelin/contracts/utils/Context.sol
/*
* @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) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
// File: @openzeppelin/contracts/utils/Strings.sol
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant alphabet = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = alphabet[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
// File: @openzeppelin/contracts/utils/introspection/ERC165.sol
/**
* @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;
}
}
// File: @openzeppelin/contracts/token/ERC721/ERC721.sol
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping (uint256 => address) private _owners;
// Mapping owner address to token count
mapping (address => uint256) private _balances;
// Mapping from token ID to approved address
mapping (uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping (address => mapping (address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor (string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IERC721).interfaceId
|| interfaceId == type(IERC721Metadata).interfaceId
|| super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0
? string(abi.encodePacked(baseURI, tokenId.toString()))
: '';
}
/**
* @dev Base URI for computing {tokenURI}. Empty by default, can be overriden
* in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
require(operator != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @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.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {
_mint(to, tokenId);
require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
private returns (bool)
{
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
// solhint-disable-next-line no-inline-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }
}
// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds
* enumerability of all the token ids in the contract as well as all token ids owned by each
* account.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
// Mapping from owner to list of owned token IDs
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] private _allTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) private _allTokensIndex;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId
|| super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
if (from == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (from != to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (to != from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
}
// File: @openzeppelin/contracts/utils/cryptography/ECDSA.sol
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
// Check the signature length
if (signature.length != 65) {
revert("ECDSA: invalid signature length");
}
// Divide the signature in r, s and v variables
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
// solhint-disable-next-line no-inline-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return recover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value");
require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value");
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
require(signer != address(0), "ECDSA: invalid signature");
return signer;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
// File: @openzeppelin/contracts/proxy/Clones.sol
/**
* @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for
* deploying minimal proxy contracts, also known as "clones".
*
* > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
* > a minimal bytecode implementation that delegates all calls to a known, fixed address.
*
* The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
* (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
* deterministic method.
*
* _Available since v3.4._
*/
library Clones {
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create opcode, which should never revert.
*/
function clone(address implementation) internal returns (address instance) {
// solhint-disable-next-line no-inline-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create(0, ptr, 0x37)
}
require(instance != address(0), "ERC1167: create failed");
}
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create2 opcode and a `salt` to deterministically deploy
* the clone. Using the same `implementation` and `salt` multiple time will revert, since
* the clones cannot be deployed twice at the same address.
*/
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
// solhint-disable-next-line no-inline-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create2(0, ptr, 0x37, salt)
}
require(instance != address(0), "ERC1167: create2 failed");
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(address implementation, bytes32 salt, address deployer) internal pure returns (address predicted) {
// solhint-disable-next-line no-inline-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
mstore(add(ptr, 0x38), shl(0x60, deployer))
mstore(add(ptr, 0x4c), salt)
mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
predicted := keccak256(add(ptr, 0x37), 0x55)
}
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(address implementation, bytes32 salt) internal view returns (address predicted) {
return predictDeterministicAddress(implementation, salt, address(this));
}
}
// File: contracts/ENSReverseRegistrarI.sol
/*
* Interfaces for ENS Reverse Registrar
* See https://github.com/ensdomains/ens/blob/master/contracts/ReverseRegistrar.sol for full impl
* Also see https://github.com/wealdtech/wealdtech-solidity/blob/master/contracts/ens/ENSReverseRegister.sol
*
* Use this as follows (registryAddress is the address of the ENS registry to use):
* -----
* // This hex value is caclulated by namehash('addr.reverse')
* bytes32 public constant ENS_ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;
* function registerReverseENS(address registryAddress, string memory calldata) external {
* require(registryAddress != address(0), "need a valid registry");
* address reverseRegistrarAddress = ENSRegistryOwnerI(registryAddress).owner(ENS_ADDR_REVERSE_NODE)
* require(reverseRegistrarAddress != address(0), "need a valid reverse registrar");
* ENSReverseRegistrarI(reverseRegistrarAddress).setName(name);
* }
* -----
* or
* -----
* function registerReverseENS(address reverseRegistrarAddress, string memory calldata) external {
* require(reverseRegistrarAddress != address(0), "need a valid reverse registrar");
* ENSReverseRegistrarI(reverseRegistrarAddress).setName(name);
* }
* -----
* ENS deployments can be found at https://docs.ens.domains/ens-deployments
* E.g. Etherscan can be used to look up that owner on those contracts.
* namehash.hash("addr.reverse") == "0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2"
* Ropsten: ens.owner(namehash.hash("addr.reverse")) == "0x6F628b68b30Dc3c17f345c9dbBb1E483c2b7aE5c"
* Mainnet: ens.owner(namehash.hash("addr.reverse")) == "0x084b1c3C81545d370f3634392De611CaaBFf8148"
*/
interface ENSRegistryOwnerI {
function owner(bytes32 node) external view returns (address);
}
interface ENSReverseRegistrarI {
event NameChanged(bytes32 indexed node, string name);
/**
* @dev Sets the `name()` record for the reverse ENS record associated with
* the calling account.
* @param name The name to set for this address.
* @return The ENS node hash of the reverse record.
*/
function setName(string calldata name) external returns (bytes32);
}
// File: contracts/ERC721SignedTransferI.sol
/*
* Interface for ERC721 Signed Transfers.
*/
/**
* @dev Outward-facing interface of a Collections contract.
*/
interface ERC721SignedTransferI is IERC721 {
/**
* @dev Emitted when a signed transfer is being executed.
*/
event SignedTransfer(address operator, address indexed from, address indexed to, uint256 indexed tokenId, uint256 signedTransferNonce);
/**
* @dev The signed transfer nonce for an account.
*/
function signedTransferNonce(address account) external view returns (uint256);
/**
* @dev Outward-facing function for signed transfer: assembles the expected data and then calls the internal function to do the rest.
* Can called by anyone knowing about the right signature, but can only transfer to the given specific target.
*/
function signedTransfer(uint256 tokenId, address to, bytes memory signature) external;
/**
* @dev Outward-facing function for operator-driven signed transfer: assembles the expected data and then calls the internal function to do the rest.
* Can transfer to any target, but only be called by the trusted operator contained in the signature.
*/
function signedTransferWithOperator(uint256 tokenId, address to, bytes memory signature) external;
}
// File: contracts/CollectionsI.sol
/*
* Interface for the Collections factory.
*/
/**
* @dev Outward-facing interface of a Collections contract.
*/
interface CollectionsI is IERC721 {
/**
* @dev Emitted when a new collection is created.
*/
event NewCollection(address indexed owner, address collectionAddress);
/**
* @dev Emitted when a collection is destroyed.
*/
event KilledCollection(address indexed owner, address collectionAddress);
/**
* @dev Creates a new Collection. For calling from other contracts,
* returns the address of the new Collection.
*/
function create(address _notificationContract,
string calldata _ensName,
string calldata _ensSubdomainName,
address _ensSubdomainRegistrarAddress,
address _ensReverseRegistrarAddress)
external payable
returns (address);
/**
* @dev Create a collection for a different owner. Only callable by a
* create controller role. For calling from other contracts, returns the
* address of the new Collection.
*/
function createFor(address payable _newOwner,
address _notificationContract,
string calldata _ensName,
string calldata _ensSubdomainName,
address _ensSubdomainRegistrarAddress,
address _ensReverseRegistrarAddress)
external payable
returns (address);
/**
* @dev Removes (burns) an empty Collection. Only the Collection contract itself can call this.
*/
function burn(uint256 tokenId) external;
/**
* @dev Returns if a Collection NFT exists for the specified `tokenId`.
*/
function exists(uint256 tokenId) external view returns (bool);
/**
* @dev Returns whether the given spender can transfer a given `collectionAddr`.
*/
function isApprovedOrOwnerOnCollection(address spender, address collectionAddr) external view returns (bool);
/**
* @dev Returns the Collection address for a token ID.
*/
function collectionAddress(uint256 tokenId) external view returns (address);
/**
* @dev Returns the token ID for a Collection address.
*/
function tokenIdForCollection(address collectionAddr) external view returns (uint256);
/**
* @dev Returns true if a Collection exists at this address, false if not.
*/
function collectionExists(address collectionAddr) external view returns (bool);
/**
* @dev Returns the owner of the Collection with the given address.
*/
function collectionOwner(address collectionAddr) external view returns (address);
/**
* @dev Returns a Collection address owned by `owner` at a given `index` of
* its Collections list. Mirrors `tokenOfOwnerByIndex` in ERC721Enumerable.
*/
function collectionOfOwnerByIndex(address owner, uint256 index) external view returns (address);
}
// File: @openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol
/**
* _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);
}
// File: contracts/CollectionI.sol
/*
* Interface for a single Collection, which is a very lightweight contract that can be the owner of ERC721 tokens.
*/
interface CollectionI is IERC165, IERC721Receiver, IERC1155Receiver {
/**
* @dev Emitted when the notification conmtract is changed.
*/
event NotificationContractTransferred(address indexed previousNotificationContract, address indexed newNotificationContract);
/**
* @dev Emitted when an asset is added to the collection.
*/
event AssetAdded(address tokenAddress, uint256 tokenId);
/**
* @dev Emitted when an asset is removed to the collection.
*/
event AssetRemoved(address tokenAddress, uint256 tokenId);
/**
* @dev Emitted when the Collection is destroyed.
*/
event CollectionDestroyed(address operator);
/**
* @dev True is this is the prototype, false if this is an active
* (clone/proxy) collection contract.
*/
function isPrototype() external view returns (bool);
/**
* @dev The linked Collections factory (the ERC721 contract).
*/
function collections() external view returns (CollectionsI);
/**
* @dev The linked notification contract (e.g. achievements).
*/
function notificationContract() external view returns (address);
/**
* @dev Initializes a new Collection. Needs to be called by the Collections
* factory.
*/
function initialRegister(address _notificationContract,
string calldata _ensName,
string calldata _ensSubdomainName,
address _ensSubdomainRegistrarAddress,
address _ensReverseRegistrarAddress)
external;
/**
* @dev Switch the notification contract to a different address. Set to the
* zero address to disable notifications. Can only be called by owner.
*/
function transferNotificationContract(address _newNotificationContract) external;
/**
* @dev Get collection owner from ERC 721 parent (Collections factory).
*/
function ownerAddress() external view returns (address);
/**
* @dev Determine if the Collection owns a specific asset.
*/
function ownsAsset(address _tokenAddress, uint256 _tokenId) external view returns(bool);
/**
* @dev Get count of owned assets.
*/
function ownedAssetsCount() external view returns (uint256);
/**
* @dev Make sure ownership of a certain asset is recorded correctly (added
* if the collection owns it or removed if it doesn't).
*/
function syncAssetOwnership(address _tokenAddress, uint256 _tokenId) external;
/**
* @dev Transfer an owned asset to a new owner (for ERC1155, a single item
* of that asset).
*/
function safeTransferTo(address _tokenAddress, uint256 _tokenId, address _to) external;
/**
* @dev Transfer a certain amount of an owned asset to a new owner (for
* ERC721, _value is ignored).
*/
function safeTransferTo(address _tokenAddress, uint256 _tokenId, address _to, uint256 _value) external;
/**
* @dev Destroy and burn an empty Collection. Can only be called by owner
* and only on empty collections.
*/
function destroy() external;
/**
* @dev Forward calls to external contracts. Can only be called by owner.
* Given a contract address and an already-encoded payload (with a function
* call etc.), we call that contract with this payload, e.g. to trigger
* actions in the name of the collection.
*/
function externalCall(address payable _remoteAddress, bytes calldata _callPayload) external payable;
/**
* @dev Register ENS name. Can only be called by owner.
*/
function registerENS(string calldata _name, address _registrarAddress) external;
/**
* @dev Register Reverse ENS name. Can only be called by owner.
*/
function registerReverseENS(address _reverseRegistrarAddress, string calldata _name) external;
}
// File: contracts/MultiOracleRequestI.sol
/*
* Interface for requests to the multi-rate oracle (for EUR/ETH and ERC20)
* Copy this to projects that need to access the oracle.
* This is a strict superset of OracleRequestI to ensure compatibility.
* See rate-oracle project for implementation.
*/
interface MultiOracleRequestI {
/**
* @dev Number of wei per EUR
*/
function EUR_WEI() external view returns (uint256); // solhint-disable func-name-mixedcase
/**
* @dev Timestamp of when the last update for the ETH rate occurred
*/
function lastUpdate() external view returns (uint256);
/**
* @dev Number of EUR per ETH (rounded down!)
*/
function ETH_EUR() external view returns (uint256); // solhint-disable func-name-mixedcase
/**
* @dev Number of EUR cent per ETH (rounded down!)
*/
function ETH_EURCENT() external view returns (uint256); // solhint-disable func-name-mixedcase
/**
* @dev True for ERC20 tokens that are supported by this oracle, false otherwise
*/
function tokenSupported(address tokenAddress) external view returns(bool);
/**
* @dev Number of token units per EUR
*/
function eurRate(address tokenAddress) external view returns(uint256);
/**
* @dev Timestamp of when the last update for the specific ERC20 token rate occurred
*/
function lastRateUpdate(address tokenAddress) external view returns (uint256);
/**
* @dev Emitted on rate update - using address(0) as tokenAddress for ETH updates
*/
event RateUpdated(address indexed tokenAddress, uint256 indexed eurRate);
}
// File: contracts/BridgeDataI.sol
/*
* Interface for data storage of the bridge.
*/
interface BridgeDataI {
event AddressChanged(string name, address previousAddress, address newAddress);
event ConnectedChainChanged(string previousConnectedChainName, string newConnectedChainName);
event TokenURIBaseChanged(string previousTokenURIBase, string newTokenURIBase);
event TokenSunsetAnnounced(uint256 indexed timestamp);
/**
* @dev The name of the chain connected to / on the other side of this bridge head.
*/
function connectedChainName() external view returns (string memory);
/**
* @dev The name of our own chain, used in token URIs handed to deployed tokens.
*/
function ownChainName() external view returns (string memory);
/**
* @dev The base of ALL token URIs, e.g. https://example.com/
*/
function tokenURIBase() external view returns (string memory);
/**
* @dev The sunset timestamp for all deployed tokens.
* If 0, no sunset is in place. Otherwise, if older than block timestamp,
* all transfers of the tokens are frozen.
*/
function tokenSunsetTimestamp() external view returns (uint256);
/**
* @dev Set a token sunset timestamp.
*/
function setTokenSunsetTimestamp(uint256 _timestamp) external;
/**
* @dev Set an address for a name.
*/
function setAddress(string memory name, address newAddress) external;
/**
* @dev Get an address for a name.
*/
function getAddress(string memory name) external view returns (address);
}
// File: contracts/Collections.sol
/*
* Implements Collections of ERC 721 tokens, exposed as yet another ERC721 token.
*/
contract Collections is ERC721Enumerable, CollectionsI, ERC721SignedTransferI {
using Address for address payable;
BridgeDataI public bridgeData;
uint256 public priceEurCent;
mapping(address => bool) public freeCreator;
address public collectionPrototypeAddress;
mapping(address => uint256) public override signedTransferNonce;
event BridgeDataChanged(address indexed previousBridgeData, address indexed newBridgeData);
event FreeCreatorSet(address indexed freeAddress, bool enabled);
event PriceChanged(uint256 previousPriceEurCent, uint256 newPriceEurCent);
// Collection event - never emitted in this contract but helpful for running our tests.
event NotificationContractTransferred(address indexed previousNotificationContract, address indexed newNotificationContract);
// TestTracker event - never emitted in this contract but helpful for running our tests.
event SeenContractAdded(bool initial);
constructor(address _bridgeDataAddress, uint256 _priceEurCent, address _collectionPrototypeAddress)
ERC721("Crypto stamp Collections", "CSC")
{
bridgeData = BridgeDataI(_bridgeDataAddress);
require(address(bridgeData) != address(0x0), "You need to provide an actual bridge data contract.");
priceEurCent = _priceEurCent;
require(priceEurCent > 0, "You need to provide a non-zero price.");
require(CollectionI(_collectionPrototypeAddress).isPrototype(), "_collectionPrototypeAddress needs to be a prototype.");
collectionPrototypeAddress = _collectionPrototypeAddress;
}
modifier onlyShopControl()
{
require(msg.sender == bridgeData.getAddress("shopControl"), "shopControl key required for this function.");
_;
}
modifier onlyTokenAssignmentControl() {
require(msg.sender == bridgeData.getAddress("tokenAssignmentControl"), "tokenAssignmentControl key required for this function.");
_;
}
modifier requireTransferEnabled() {
require(transferEnabled() == true, "This call only works when transfers are enabled.");
_;
}
/*** Enable adjusting variables after deployment ***/
function setBridgeData(BridgeDataI _newBridgeData)
external
onlyShopControl
{
require(address(_newBridgeData) != address(0x0), "You need to provide an actual bridge data contract.");
emit BridgeDataChanged(address(bridgeData), address(_newBridgeData));
bridgeData = _newBridgeData;
}
function setFreeCreators(address[] memory _freeAddresses, bool _enabled)
public
onlyShopControl
{
uint256 addrcount = _freeAddresses.length;
for (uint256 i = 0; i < addrcount; i++) {
freeCreator[_freeAddresses[i]] = _enabled;
emit FreeCreatorSet(_freeAddresses[i], _enabled);
}
}
function setPrice(uint256 _newPriceEurCent)
public
onlyShopControl
{
require(_newPriceEurCent > 0, "You need to provide a non-zero price.");
emit PriceChanged(priceEurCent, _newPriceEurCent);
priceEurCent = _newPriceEurCent;
}
// Calculate current asset price in "wei" (subunits of the native chain currency).
// Note: Price in EUR cent is available from public var getter priceEurCent().
function priceWei()
public view
returns (uint256)
{
return priceEurCent * MultiOracleRequestI(bridgeData.getAddress("Oracle")).eurRate(address(0)) / 100;
}
function baseURI() public view returns (string memory) {
return _baseURI();
}
function _baseURI() internal view override returns (string memory) {
return string(abi.encodePacked(bridgeData.tokenURIBase(), symbol(), "/meta/"));
}
// Return true if transfers are possible.
// This can have additional conditions to just the sunset variable.
function transferEnabled()
public view
returns (bool)
{
uint256 tokenSunsetTimestamp = bridgeData.tokenSunsetTimestamp();
// solhint-disable-next-line not-rely-on-time
return (tokenSunsetTimestamp == 0 || tokenSunsetTimestamp > block.timestamp);
}
/*** Override internal functionality for special rules on approvals and transfers ***/
// When the bridge is sunset, all token actions will be blocked.
function _beforeTokenTransfer(address _from, address _to, uint256 _tokenId)
internal override
requireTransferEnabled
{
super._beforeTokenTransfer(_from, _to, _tokenId);
}
/*** Manage collections ***/
// Issue a new collection, which will be owned by whoever calls this function.
function create(address _notificationContract,
string memory _ensName,
string memory _ensSubdomainName,
address _ensSubdomainRegistrarAddress,
address _ensReverseRegistrarAddress)
public override payable
returns (address)
{
return createFor(payable(msg.sender), _notificationContract, _ensName, _ensSubdomainName, _ensSubdomainRegistrarAddress, _ensReverseRegistrarAddress);
}
// Create a collection for a different owner.
function createFor(address payable _newOwner,
address _notificationContract,
string memory _ensName,
string memory _ensSubdomainName,
address _ensSubdomainRegistrarAddress,
address _ensReverseRegistrarAddress)
public override payable
returns (address)
{
uint256 curPriceWei = priceWei();
if (freeCreator[msg.sender] || msg.sender == bridgeData.getAddress("tokenHolder")) {
// The bridge and create control do not need to pay for creating collections.
curPriceWei = 0;
}
require(msg.value >= curPriceWei, "You need to send money to create a collection.");
address newCollectionAddress = _createCollection(_newOwner, _notificationContract, _ensName, _ensSubdomainName, _ensSubdomainRegistrarAddress, _ensReverseRegistrarAddress);
// Transfer the actual payment amount to the beneficiary.
// Our own account so no reentrancy here but put at end to be sure.
payable(bridgeData.getAddress("beneficiary")).sendValue(curPriceWei);
// Send back change money. Do this last.
if (msg.value > curPriceWei) {
_newOwner.sendValue(msg.value - curPriceWei);
}
return newCollectionAddress;
}
function _createCollection(address _newOwner,
address _notificationContract,
string memory _ensName,
string memory _ensSubdomainName,
address _ensSubdomainRegistrarAddress,
address _ensReverseRegistrarAddress)
internal
returns (address)
{
require(collectionPrototypeAddress != address(0), "Set a collection prototype first!");
address newCollectionAddress;
if (bytes(_ensName).length > 0) {
// If we have a name, clone with predictable address based on it,
// and use the same strategy as for an ENS "label" to generate the salt for cloning.
bytes32 cloneSalt = keccak256(bytes(_ensName));
newCollectionAddress = Clones.cloneDeterministic(collectionPrototypeAddress, cloneSalt);
}
else {
// If a Collection may be created without name, use "classic" cloning.
newCollectionAddress = Clones.clone(collectionPrototypeAddress);
}
emit NewCollection(_newOwner, newCollectionAddress);
// _safeMint() checks if the recipient can actually receive ERC721 tokens.
_safeMint(_newOwner, addr2id(newCollectionAddress));
// Now, register notification and ENS.
CollectionI(newCollectionAddress).initialRegister(_notificationContract, _ensName, _ensSubdomainName, _ensSubdomainRegistrarAddress, _ensReverseRegistrarAddress);
return newCollectionAddress;
}
// Removes (burns) an empty Collection.
function burn(uint256 tokenId)
public override
{
address payable collAddress = payable(id2addr(tokenId));
require(msg.sender == collAddress, "Only the collection itself can burn the token.");
// The contract itself checks this, but let's check again to be really sure.
require(CollectionI(collAddress).ownedAssetsCount() == 0, "Only empty collections can be burned.");
address owner = ownerOf(tokenId);
_burn(tokenId);
emit KilledCollection(owner, collAddress);
}
// Returns whether the specified token exists
function exists(uint256 tokenId)
public view override
returns (bool)
{
return _exists(tokenId);
}
// Returns whether the given spender can transfer a given token ID.
function isApprovedOrOwnerOnCollection(address spender, address collectionAddr)
public view override
returns (bool)
{
return _isApprovedOrOwner(spender, addr2id(collectionAddr));
}
/*** Convert token IDs to Collection addresses and the other way round ***/
// Returns the Collection address for a token ID.
function collectionAddress(uint256 tokenId)
public view override
returns (address)
{
require(_exists(tokenId), "Collection needs to exist.");
return id2addr(tokenId);
}
// Returns the token ID for a Collection address.
function tokenIdForCollection(address collectionAddr)
public view override
returns (uint256)
{
uint256 tokenId = addr2id(collectionAddr);
require(_exists(tokenId), "Collection needs to exist.");
return tokenId;
}
function id2addr(uint256 tokenId)
internal pure
returns (address)
{
return address(uint160(tokenId));
}
function addr2id(address collectionAddr)
internal pure
returns (uint256)
{
return uint256(uint160(collectionAddr));
}
/*** Functions that mirror ERC721 but use addresses instead ***/
// Returns whether the specified token exists
function collectionExists(address collectionAddr)
public view override
returns (bool)
{
return _exists(addr2id(collectionAddr));
}
function collectionOwner(address collectionAddr)
public view override
returns (address)
{
return ownerOf(addr2id(collectionAddr));
}
function collectionOfOwnerByIndex(address owner, uint256 index)
public view override
returns (address)
{
return id2addr(tokenOfOwnerByIndex(owner, index));
}
/*** Allows any user to initiate a transfer with the signature of the current collection owner ***/
// Outward-facing function for signed transfer: assembles the expected data and then calls the internal function to do the rest.
// Can called by anyone knowing about the right signature, but can only transfer to the given specific target.
function signedTransfer(uint256 _tokenId, address _to, bytes memory _signature)
public override
requireTransferEnabled
{
address currentOwner = ownerOf(_tokenId);
// The signed data contains the token ID, the transfer target and a nonce.
bytes32 data = keccak256(abi.encodePacked(address(this), this.signedTransfer.selector, currentOwner, _to, _tokenId, signedTransferNonce[currentOwner]));
_signedTransferInternal(currentOwner, data, _tokenId, _to, _signature);
}
// Outward-facing function for operator-driven signed transfer: assembles the expected data and then calls the internal function to do the rest.
// Can transfer to any target, but only be called by the trusted operator contained in the signature.
function signedTransferWithOperator(uint256 _tokenId, address _to, bytes memory _signature)
public override
requireTransferEnabled
{
address currentOwner = ownerOf(_tokenId);
// The signed data contains the operator, the token ID, and a nonce. Note that we use the selector of the external function here!
bytes32 data = keccak256(abi.encodePacked(address(this), this.signedTransferWithOperator.selector, msg.sender, currentOwner, _tokenId, signedTransferNonce[currentOwner]));
_signedTransferInternal(currentOwner, data, _tokenId, _to, _signature);
}
// Actually check the signature and perform a signed transfer.
function _signedTransferInternal(address _currentOwner, bytes32 _data, uint256 _tokenId, address _to, bytes memory _signature)
internal
{
bytes32 hash = ECDSA.toEthSignedMessageHash(_data);
address signer = ECDSA.recover(hash, _signature);
require(signer == _currentOwner, "Signature needs to match parameters, nonce, and current owner.");
// Now that we checked that the signature is correct, do the actual transfer and increase the nonce.
emit SignedTransfer(msg.sender, _currentOwner, _to, _tokenId, signedTransferNonce[_currentOwner]);
signedTransferNonce[_currentOwner]++;
_safeTransfer(_currentOwner, _to, _tokenId, "");
}
/*** Enable reverse ENS registration ***/
// Call this with the address of the reverse registrar for the respecitve network and the ENS name to register.
// The reverse registrar can be found as the owner of 'addr.reverse' in the ENS system.
// See https://docs.ens.domains/ens-deployments for address of ENS deployments, e.g. Etherscan can be used to look up that owner on those.
// namehash.hash("addr.reverse") == "0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2"
// Ropsten: ens.owner(namehash.hash("addr.reverse")) == "0x6F628b68b30Dc3c17f345c9dbBb1E483c2b7aE5c"
// Mainnet: ens.owner(namehash.hash("addr.reverse")) == "0x084b1c3C81545d370f3634392De611CaaBFf8148"
function registerReverseENS(address _reverseRegistrarAddress, string calldata _name)
external
onlyTokenAssignmentControl
{
require(_reverseRegistrarAddress != address(0), "need a valid reverse registrar");
ENSReverseRegistrarI(_reverseRegistrarAddress).setName(_name);
}
/*** Make sure currency doesn't get stranded in this contract ***/
// If this contract gets a balance in some ERC20 contract after it's finished, then we can rescue it.
function rescueToken(IERC20 _foreignToken, address _to)
external
onlyTokenAssignmentControl
{
_foreignToken.transfer(_to, _foreignToken.balanceOf(address(this)));
}
// If this contract gets a balance in some ERC721 contract after it's finished, then we can rescue it.
function approveNFTrescue(IERC721 _foreignNFT, address _to)
external
onlyTokenAssignmentControl
{
_foreignNFT.setApprovalForAll(_to, true);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_bridgeDataAddress","type":"address"},{"internalType":"uint256","name":"_priceEurCent","type":"uint256"},{"internalType":"address","name":"_collectionPrototypeAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousBridgeData","type":"address"},{"indexed":true,"internalType":"address","name":"newBridgeData","type":"address"}],"name":"BridgeDataChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"freeAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"FreeCreatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"collectionAddress","type":"address"}],"name":"KilledCollection","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"collectionAddress","type":"address"}],"name":"NewCollection","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousNotificationContract","type":"address"},{"indexed":true,"internalType":"address","name":"newNotificationContract","type":"address"}],"name":"NotificationContractTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previousPriceEurCent","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPriceEurCent","type":"uint256"}],"name":"PriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"initial","type":"bool"}],"name":"SeenContractAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"signedTransferNonce","type":"uint256"}],"name":"SignedTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"_foreignNFT","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"approveNFTrescue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeData","outputs":[{"internalType":"contract BridgeDataI","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"collectionAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collectionAddr","type":"address"}],"name":"collectionExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"collectionOfOwnerByIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collectionAddr","type":"address"}],"name":"collectionOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collectionPrototypeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_notificationContract","type":"address"},{"internalType":"string","name":"_ensName","type":"string"},{"internalType":"string","name":"_ensSubdomainName","type":"string"},{"internalType":"address","name":"_ensSubdomainRegistrarAddress","type":"address"},{"internalType":"address","name":"_ensReverseRegistrarAddress","type":"address"}],"name":"create","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_newOwner","type":"address"},{"internalType":"address","name":"_notificationContract","type":"address"},{"internalType":"string","name":"_ensName","type":"string"},{"internalType":"string","name":"_ensSubdomainName","type":"string"},{"internalType":"address","name":"_ensSubdomainRegistrarAddress","type":"address"},{"internalType":"address","name":"_ensReverseRegistrarAddress","type":"address"}],"name":"createFor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"freeCreator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"collectionAddr","type":"address"}],"name":"isApprovedOrOwnerOnCollection","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceEurCent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceWei","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_reverseRegistrarAddress","type":"address"},{"internalType":"string","name":"_name","type":"string"}],"name":"registerReverseENS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_foreignToken","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"rescueToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract BridgeDataI","name":"_newBridgeData","type":"address"}],"name":"setBridgeData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_freeAddresses","type":"address[]"},{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setFreeCreators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPriceEurCent","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"signedTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"signedTransferNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"signedTransferWithOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collectionAddr","type":"address"}],"name":"tokenIdForCollection","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b506040516200413e3803806200413e83398101604081905262000034916200037d565b604080518082018252601881527f43727970746f207374616d7020436f6c6c656374696f6e73000000000000000060208083019182528351808501909452600384526243534360e81b9084015281519192916200009491600091620002ba565b508051620000aa906001906020840190620002ba565b5050600a80546001600160a01b0319166001600160a01b03861690811790915515159050620001465760405162461bcd60e51b815260206004820152603360248201527f596f75206e65656420746f2070726f7669646520616e2061637475616c20627260448201527f69646765206461746120636f6e74726163742e0000000000000000000000000060648201526084015b60405180910390fd5b600b82905581620001a85760405162461bcd60e51b815260206004820152602560248201527f596f75206e65656420746f2070726f766964652061206e6f6e2d7a65726f20706044820152643934b1b29760d91b60648201526084016200013d565b806001600160a01b031663793a796d6040518163ffffffff1660e01b815260040160206040518083038186803b158015620001e257600080fd5b505afa158015620001f7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200021d9190620003bd565b620002915760405162461bcd60e51b815260206004820152603460248201527f5f636f6c6c656374696f6e50726f746f7479706541646472657373206e65656460448201527f7320746f20626520612070726f746f747970652e00000000000000000000000060648201526084016200013d565b600d80546001600160a01b0319166001600160a01b039290921691909117905550620004239050565b828054620002c890620003e6565b90600052602060002090601f016020900481019282620002ec576000855562000337565b82601f106200030757805160ff191683800117855562000337565b8280016001018555821562000337579182015b82811115620003375782518255916020019190600101906200031a565b506200034592915062000349565b5090565b5b808211156200034557600081556001016200034a565b80516001600160a01b03811681146200037857600080fd5b919050565b60008060006060848603121562000392578283fd5b6200039d8462000360565b925060208401519150620003b46040850162000360565b90509250925092565b600060208284031215620003cf578081fd5b81518015158114620003df578182fd5b9392505050565b600181811c90821680620003fb57607f821691505b602082108114156200041d57634e487b7160e01b600052602260045260246000fd5b50919050565b613d0b80620004336000396000f3fe6080604052600436106102515760003560e01c80635c6f926911610139578063a22cb465116100b6578063c543e0fe1161007a578063c543e0fe146106c3578063c86cde8a146106e3578063c87b56dd14610703578063dd48f77414610723578063e985e9c514610743578063f36291dc1461078c57600080fd5b8063a22cb4651461062e578063a2dc49db1461064e578063accd00601461066e578063b7ec20861461068e578063b88d4fde146106a357600080fd5b806371f03793116100fd57806371f037931461059957806389b4ac04146105b95780638e8fa11f146105d957806391b7f5ed146105f957806395d89b411461061957600080fd5b80635c6f9269146105045780635ef935ee146105245780636352211e146105445780636c0360eb1461056457806370a082311461057957600080fd5b80632f745c59116101d25780634cd412d5116101965780634cd412d51461044f5780634f558e79146104645780634f6ccce71461048457806350029195146104a457806353a1397c146104b757806353cdef02146104e457600080fd5b80632f745c59146103b957806342842e0e146103d957806342966c68146103f95780634707d000146104195780634a1bb6b41461043957600080fd5b80630f574625116102195780630f5746251461031a5780631698befa1461033a57806318160ddd1461035a57806323b872dd146103795780632481bb5c1461039957600080fd5b806301ffc9a71461025657806306fdde031461028b578063081812fc146102ad57806308c6dc30146102e5578063095ea7b3146102f8575b600080fd5b34801561026257600080fd5b5061027661027136600461365d565b6107bc565b60405190151581526020015b60405180910390f35b34801561029757600080fd5b506102a06107e7565b604051610282919061390a565b3480156102b957600080fd5b506102cd6102c83660046136ff565b610879565b6040516001600160a01b039091168152602001610282565b6102cd6102f3366004613262565b610906565b34801561030457600080fd5b50610318610313366004613538565b610b37565b005b34801561032657600080fd5b50610318610335366004613717565b610c4d565b34801561034657600080fd5b5061027661035536600461330e565b610ceb565b34801561036657600080fd5b506008545b604051908152602001610282565b34801561038557600080fd5b50610318610394366004613346565b610d07565b3480156103a557600080fd5b50600a546102cd906001600160a01b031681565b3480156103c557600080fd5b5061036b6103d4366004613538565b610d38565b3480156103e557600080fd5b506103186103f4366004613346565b610dce565b34801561040557600080fd5b506103186104143660046136ff565b610de9565b34801561042557600080fd5b5061031861043436600461330e565b610f80565b34801561044557600080fd5b5061036b600b5481565b34801561045b57600080fd5b5061027661112d565b34801561047057600080fd5b5061027661047f3660046136ff565b6111ca565b34801561049057600080fd5b5061036b61049f3660046136ff565b6111d5565b6102cd6104b236600461349d565b611276565b3480156104c357600080fd5b5061036b6104d236600461322a565b600e6020526000908152604090205481565b3480156104f057600080fd5b506103186104ff36600461322a565b611290565b34801561051057600080fd5b506102cd61051f366004613538565b61140c565b34801561053057600080fd5b506102cd61053f3660046136ff565b61141e565b34801561055057600080fd5b506102cd61055f3660046136ff565b61147b565b34801561057057600080fd5b506102a06114f2565b34801561058557600080fd5b5061036b61059436600461322a565b611501565b3480156105a557600080fd5b506103186105b4366004613717565b611588565b3480156105c557600080fd5b506103186105d4366004613563565b6115fa565b3480156105e557600080fd5b506103186105f436600461341d565b61179d565b34801561060557600080fd5b506103186106143660046136ff565b611921565b34801561062557600080fd5b506102a0611a6e565b34801561063a57600080fd5b506103186106493660046133f0565b611a7d565b34801561065a57600080fd5b50600d546102cd906001600160a01b031681565b34801561067a57600080fd5b5061027661068936600461322a565b611b42565b34801561069a57600080fd5b5061036b611b56565b3480156106af57600080fd5b506103186106be366004613386565b611c7e565b3480156106cf57600080fd5b506102cd6106de36600461322a565b611cb0565b3480156106ef57600080fd5b5061036b6106fe36600461322a565b611cc4565b34801561070f57600080fd5b506102a061071e3660046136ff565b611d25565b34801561072f57600080fd5b5061031861073e36600461330e565b611def565b34801561074f57600080fd5b5061027661075e36600461330e565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b34801561079857600080fd5b506102766107a736600461322a565b600c6020526000908152604090205460ff1681565b60006001600160e01b0319821663780e9d6360e01b14806107e157506107e182611f03565b92915050565b6060600080546107f690613bed565b80601f016020809104026020016040519081016040528092919081815260200182805461082290613bed565b801561086f5780601f106108445761010080835404028352916020019161086f565b820191906000526020600020905b81548152906001019060200180831161085257829003601f168201915b5050505050905090565b600061088482611f53565b6108ea5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600080610911611b56565b336000908152600c602052604090205490915060ff16806109d95750600a5460405163bf40fac160e01b815260206004820152600b60248201526a3a37b5b2b72437b63232b960a91b60448201526001600160a01b039091169063bf40fac19060640160206040518083038186803b15801561098c57600080fd5b505afa1580156109a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c49190613246565b6001600160a01b0316336001600160a01b0316145b156109e2575060005b80341015610a495760405162461bcd60e51b815260206004820152602e60248201527f596f75206e65656420746f2073656e64206d6f6e657920746f2063726561746560448201526d10309031b7b63632b1ba34b7b71760911b60648201526084016108e1565b6000610a59898989898989611f70565b600a5460405163bf40fac160e01b815260206004820152600b60248201526a62656e656669636961727960a81b6044820152919250610b069184916001600160a01b03169063bf40fac19060640160206040518083038186803b158015610abf57600080fd5b505afa158015610ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af79190613246565b6001600160a01b0316906120e1565b81341115610b2b57610b2b610b1b8334613baa565b6001600160a01b038b16906120e1565b98975050505050505050565b6000610b428261147b565b9050806001600160a01b0316836001600160a01b03161415610bb05760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084016108e1565b336001600160a01b0382161480610bcc5750610bcc813361075e565b610c3e5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c000000000000000060648201526084016108e1565b610c4883836121fa565b505050565b610c5561112d565b1515600114610c765760405162461bcd60e51b81526004016108e19061399f565b6000610c818461147b565b6001600160a01b0381166000908152600e602090815260408083205490519394509192610cbf923092630f57462560e01b92339288928c920161379a565b604051602081830303815290604052805190602001209050610ce48282878787612268565b5050505050565b6000610d00836001600160a01b0384166123fd565b9392505050565b610d1133826123fd565b610d2d5760405162461bcd60e51b81526004016108e190613a6a565b610c488383836124e7565b6000610d4383611501565b8210610da55760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016108e1565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b610c4883838360405180602001604052806000815250611c7e565b806001600160a01b0381163314610e595760405162461bcd60e51b815260206004820152602e60248201527f4f6e6c792074686520636f6c6c656374696f6e20697473656c662063616e206260448201526d3ab937103a3432903a37b5b2b71760911b60648201526084016108e1565b806001600160a01b03166355c857fe6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e9257600080fd5b505afa158015610ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eca9190613645565b15610f255760405162461bcd60e51b815260206004820152602560248201527f4f6e6c7920656d70747920636f6c6c656374696f6e732063616e206265206275604482015264393732b21760d91b60648201526084016108e1565b6000610f308361147b565b9050610f3b83612692565b6040516001600160a01b0383811682528216907fe234f7a6922ece586c80e5ffab3cbc7b8a57d40e8b86753d858ee5bd25efebf39060200160405180910390a2505050565b600a5460405163bf40fac160e01b81526001600160a01b039091169063bf40fac190610fae9060040161396f565b60206040518083038186803b158015610fc657600080fd5b505afa158015610fda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ffe9190613246565b6001600160a01b0316336001600160a01b03161461102e5760405162461bcd60e51b81526004016108e1906139ef565b6040516370a0823160e01b81523060048201526001600160a01b0383169063a9059cbb90839083906370a082319060240160206040518083038186803b15801561107757600080fd5b505afa15801561108b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110af9190613645565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b1580156110f557600080fd5b505af1158015611109573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c489190613629565b600080600a60009054906101000a90046001600160a01b03166001600160a01b031663a564a2e06040518163ffffffff1660e01b815260040160206040518083038186803b15801561117e57600080fd5b505afa158015611192573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b69190613645565b90508015806111c457504281115b91505090565b60006107e182611f53565b60006111e060085490565b82106112435760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b60648201526084016108e1565b6008828154811061126457634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b6000611286338787878787610906565b9695505050505050565b600a5460405163bf40fac160e01b81526001600160a01b039091169063bf40fac1906112be90600401613a45565b60206040518083038186803b1580156112d657600080fd5b505afa1580156112ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130e9190613246565b6001600160a01b0316336001600160a01b03161461133e5760405162461bcd60e51b81526004016108e190613abb565b6001600160a01b0381166113b05760405162461bcd60e51b815260206004820152603360248201527f596f75206e65656420746f2070726f7669646520616e2061637475616c20627260448201527234b233b2903230ba309031b7b73a3930b1ba1760691b60648201526084016108e1565b600a546040516001600160a01b038084169216907f6a6e057f21cc834cf349d8150e92867f52cb34d54375f174c09c431538c3dfb990600090a3600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6000610d0061141b8484610d38565b90565b600061142982611f53565b6114755760405162461bcd60e51b815260206004820152601a60248201527f436f6c6c656374696f6e206e6565647320746f2065786973742e00000000000060448201526064016108e1565b816107e1565b6000818152600260205260408120546001600160a01b0316806107e15760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b60648201526084016108e1565b60606114fc612739565b905090565b60006001600160a01b03821661156c5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b60648201526084016108e1565b506001600160a01b031660009081526003602052604090205490565b61159061112d565b15156001146115b15760405162461bcd60e51b81526004016108e19061399f565b60006115bc8461147b565b6001600160a01b0381166000908152600e602090815260408083205490519394509192610cbf9230926371f0379360e01b9287928a928c920161379a565b600a5460405163bf40fac160e01b81526001600160a01b039091169063bf40fac19061162890600401613a45565b60206040518083038186803b15801561164057600080fd5b505afa158015611654573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116789190613246565b6001600160a01b0316336001600160a01b0316146116a85760405162461bcd60e51b81526004016108e190613abb565b815160005b818110156117975782600c60008684815181106116da57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555083818151811061173957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03167fef831a7da9050b3ebdfc86f7ecf0268d61828bd15ebcfe20611cb09f55e8f3088460405161177d911515815260200190565b60405180910390a28061178f81613c28565b9150506116ad565b50505050565b600a5460405163bf40fac160e01b81526001600160a01b039091169063bf40fac1906117cb9060040161396f565b60206040518083038186803b1580156117e357600080fd5b505afa1580156117f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181b9190613246565b6001600160a01b0316336001600160a01b03161461184b5760405162461bcd60e51b81526004016108e1906139ef565b6001600160a01b0383166118a15760405162461bcd60e51b815260206004820152601e60248201527f6e65656420612076616c6964207265766572736520726567697374726172000060448201526064016108e1565b60405163c47f002760e01b81526001600160a01b0384169063c47f0027906118cf90859085906004016138db565b602060405180830381600087803b1580156118e957600080fd5b505af11580156118fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117979190613645565b600a5460405163bf40fac160e01b81526001600160a01b039091169063bf40fac19061194f90600401613a45565b60206040518083038186803b15801561196757600080fd5b505afa15801561197b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061199f9190613246565b6001600160a01b0316336001600160a01b0316146119cf5760405162461bcd60e51b81526004016108e190613abb565b60008111611a2d5760405162461bcd60e51b815260206004820152602560248201527f596f75206e65656420746f2070726f766964652061206e6f6e2d7a65726f20706044820152643934b1b29760d91b60648201526084016108e1565b600b5460408051918252602082018390527f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68910160405180910390a1600b55565b6060600180546107f690613bed565b6001600160a01b038216331415611ad65760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016108e1565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60006107e16001600160a01b038316611f53565b600a5460405163bf40fac160e01b81526020600482015260066024820152654f7261636c6560d01b60448201526000916064916001600160a01b039091169063bf40fac190830160206040518083038186803b158015611bb557600080fd5b505afa158015611bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bed9190613246565b60405163048cc1a760e51b8152600060048201526001600160a01b03919091169063919834e09060240160206040518083038186803b158015611c2f57600080fd5b505afa158015611c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c679190613645565b600b54611c749190613b8b565b6114fc9190613b77565b611c8833836123fd565b611ca45760405162461bcd60e51b81526004016108e190613a6a565b611797848484846127e7565b60006107e16001600160a01b03831661147b565b60006001600160a01b038216611cd981611f53565b6107e15760405162461bcd60e51b815260206004820152601a60248201527f436f6c6c656374696f6e206e6565647320746f2065786973742e00000000000060448201526064016108e1565b6060611d3082611f53565b611d945760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b60648201526084016108e1565b6000611d9e612739565b90506000815111611dbe5760405180602001604052806000815250610d00565b80611dc88461281a565b604051602001611dd99291906137ea565b6040516020818303038152906040529392505050565b600a5460405163bf40fac160e01b81526001600160a01b039091169063bf40fac190611e1d9060040161396f565b60206040518083038186803b158015611e3557600080fd5b505afa158015611e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6d9190613246565b6001600160a01b0316336001600160a01b031614611e9d5760405162461bcd60e51b81526004016108e1906139ef565b60405163a22cb46560e01b81526001600160a01b0382811660048301526001602483015283169063a22cb46590604401600060405180830381600087803b158015611ee757600080fd5b505af1158015611efb573d6000803e3d6000fd5b505050505050565b60006001600160e01b031982166380ac58cd60e01b1480611f3457506001600160e01b03198216635b5e139f60e01b145b806107e157506301ffc9a760e01b6001600160e01b03198316146107e1565b6000908152600260205260409020546001600160a01b0316151590565b600d546000906001600160a01b0316611fd55760405162461bcd60e51b815260206004820152602160248201527f536574206120636f6c6c656374696f6e2070726f746f747970652066697273746044820152602160f81b60648201526084016108e1565b8451600090156120045785516020870120600d54611ffc906001600160a01b031682612934565b91505061201c565b600d54612019906001600160a01b03166129d4565b90505b6040516001600160a01b0382811682528916907f5b84d9550adb7000df7bee717735ecd3af48ea3f66c6886d52e8227548fb228c9060200160405180910390a261206f886001600160a01b038316612a71565b604051632337dc9b60e21b81526001600160a01b03821690638cdf726c906120a3908a908a908a908a908a9060040161388c565b600060405180830381600087803b1580156120bd57600080fd5b505af11580156120d1573d6000803e3d6000fd5b50929a9950505050505050505050565b804710156121315760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016108e1565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461217e576040519150601f19603f3d011682016040523d82523d6000602084013e612183565b606091505b5050905080610c485760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016108e1565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061222f8261147b565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006122c1856040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b905060006122cf8284612a8f565b9050866001600160a01b0316816001600160a01b0316146123585760405162461bcd60e51b815260206004820152603e60248201527f5369676e6174757265206e6565647320746f206d6174636820706172616d657460448201527f6572732c206e6f6e63652c20616e642063757272656e74206f776e65722e000060648201526084016108e1565b6001600160a01b038781166000818152600e6020908152604091829020548251338152918201528893881692917fba05f551fcc429cba611372aa0055e3573f26273f66d1a48bdb5b4f7896bf022910160405180910390a46001600160a01b0387166000908152600e602052604081208054916123d483613c28565b91905055506123f4878587604051806020016040528060008152506127e7565b50505050505050565b600061240882611f53565b6124695760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084016108e1565b60006124748361147b565b9050806001600160a01b0316846001600160a01b031614806124af5750836001600160a01b03166124a484610879565b6001600160a01b0316145b806124df57506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b03166124fa8261147b565b6001600160a01b0316146125625760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b60648201526084016108e1565b6001600160a01b0382166125c45760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016108e1565b6125cf838383612b00565b6125da6000826121fa565b6001600160a01b0383166000908152600360205260408120805460019290612603908490613baa565b90915550506001600160a01b0382166000908152600360205260408120805460019290612631908490613b5f565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061269d8261147b565b90506126ab81600084612b00565b6126b66000836121fa565b6001600160a01b03811660009081526003602052604081208054600192906126df908490613baa565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b600a546040805163261220a360e01b815290516060926001600160a01b03169163261220a3916004808301926000929190829003018186803b15801561277e57600080fd5b505afa158015612792573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127ba9190810190613695565b6127c2611a6e565b6040516020016127d3929190613819565b604051602081830303815290604052905090565b6127f28484846124e7565b6127fe84848484612b34565b6117975760405162461bcd60e51b81526004016108e19061391d565b60608161283e5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612868578061285281613c28565b91506128619050600a83613b77565b9150612842565b60008167ffffffffffffffff81111561289157634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156128bb576020820181803683370190505b5090505b84156124df576128d0600183613baa565b91506128dd600a86613c43565b6128e8906030613b5f565b60f81b81838151811061290b57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535061292d600a86613b77565b94506128bf565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152826037826000f59150506001600160a01b0381166107e15760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c656400000000000000000060448201526064016108e1565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116612a6c5760405162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b60448201526064016108e1565b919050565b612a8b828260405180602001604052806000815250612c41565b5050565b60008151604114612ae25760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016108e1565b60208201516040830151606084015160001a61128686828585612c74565b612b0861112d565b1515600114612b295760405162461bcd60e51b81526004016108e19061399f565b610c48838383612e1d565b60006001600160a01b0384163b15612c3657604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612b78903390899088908890600401613859565b602060405180830381600087803b158015612b9257600080fd5b505af1925050508015612bc2575060408051601f3d908101601f19168201909252612bbf91810190613679565b60015b612c1c573d808015612bf0576040519150601f19603f3d011682016040523d82523d6000602084013e612bf5565b606091505b508051612c145760405162461bcd60e51b81526004016108e19061391d565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506124df565b506001949350505050565b612c4b8383612ed5565b612c586000848484612b34565b610c485760405162461bcd60e51b81526004016108e19061391d565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612cf15760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016108e1565b8360ff16601b1480612d0657508360ff16601c145b612d5d5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016108e1565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015612db1573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612e145760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016108e1565b95945050505050565b6001600160a01b038316612e7857612e7381600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b612e9b565b816001600160a01b0316836001600160a01b031614612e9b57612e9b8382613014565b6001600160a01b038216612eb257610c48816130b1565b826001600160a01b0316826001600160a01b031614610c4857610c48828261318a565b6001600160a01b038216612f2b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016108e1565b612f3481611f53565b15612f815760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016108e1565b612f8d60008383612b00565b6001600160a01b0382166000908152600360205260408120805460019290612fb6908490613b5f565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000600161302184611501565b61302b9190613baa565b60008381526007602052604090205490915080821461307e576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b6008546000906130c390600190613baa565b600083815260096020526040812054600880549394509092849081106130f957634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050806008838154811061312857634e487b7160e01b600052603260045260246000fd5b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061316e57634e487b7160e01b600052603160045260246000fd5b6001900381819060005260206000200160009055905550505050565b600061319583611501565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b8035612a6c81613cb1565b600082601f8301126131e9578081fd5b81356131fc6131f782613b37565b613b06565b818152846020838601011115613210578283fd5b816020850160208301379081016020019190915292915050565b60006020828403121561323b578081fd5b8135610d0081613c99565b600060208284031215613257578081fd5b8151610d0081613c99565b60008060008060008060c0878903121561327a578182fd5b863561328581613c99565b9550602087013561329581613c99565b9450604087013567ffffffffffffffff808211156132b1578384fd5b6132bd8a838b016131d9565b955060608901359150808211156132d2578384fd5b506132df89828a016131d9565b93505060808701356132f081613c99565b915060a087013561330081613c99565b809150509295509295509295565b60008060408385031215613320578182fd5b823561332b81613c99565b9150602083013561333b81613c99565b809150509250929050565b60008060006060848603121561335a578283fd5b833561336581613c99565b9250602084013561337581613c99565b929592945050506040919091013590565b6000806000806080858703121561339b578182fd5b84356133a681613c99565b935060208501356133b681613c99565b925060408501359150606085013567ffffffffffffffff8111156133d8578182fd5b6133e4878288016131d9565b91505092959194509250565b60008060408385031215613402578182fd5b823561340d81613c99565b9150602083013561333b81613cb1565b600080600060408486031215613431578081fd5b833561343c81613c99565b9250602084013567ffffffffffffffff80821115613458578283fd5b818601915086601f83011261346b578283fd5b813581811115613479578384fd5b87602082850101111561348a578384fd5b6020830194508093505050509250925092565b600080600080600060a086880312156134b4578283fd5b85356134bf81613c99565b9450602086013567ffffffffffffffff808211156134db578485fd5b6134e789838a016131d9565b955060408801359150808211156134fc578485fd5b50613509888289016131d9565b935050606086013561351a81613c99565b9150608086013561352a81613c99565b809150509295509295909350565b6000806040838503121561354a578182fd5b823561355581613c99565b946020939093013593505050565b60008060408385031215613575578182fd5b823567ffffffffffffffff8082111561358c578384fd5b818501915085601f83011261359f578384fd5b81356020828211156135b3576135b3613c83565b8160051b92506135c4818401613b06565b8281528181019085830185870184018b10156135de578889fd5b8896505b8487101561360c57803595506135f786613c99565b858352600196909601959183019183016135e2565b50965061361c90508782016131ce565b9450505050509250929050565b60006020828403121561363a578081fd5b8151610d0081613cb1565b600060208284031215613656578081fd5b5051919050565b60006020828403121561366e578081fd5b8135610d0081613cbf565b60006020828403121561368a578081fd5b8151610d0081613cbf565b6000602082840312156136a6578081fd5b815167ffffffffffffffff8111156136bc578182fd5b8201601f810184136136cc578182fd5b80516136da6131f782613b37565b8181528560208385010111156136ee578384fd5b612e14826020830160208601613bc1565b600060208284031215613710578081fd5b5035919050565b60008060006060848603121561372b578081fd5b83359250602084013561373d81613c99565b9150604084013567ffffffffffffffff811115613758578182fd5b613764868287016131d9565b9150509250925092565b60008151808452613786816020860160208601613bc1565b601f01601f19169290920160200192915050565b6bffffffffffffffffffffffff19606097881b811682526001600160e01b031996909616601482015293861b8516601885015291851b909316602c83015260408201929092529182015260800190565b600083516137fc818460208801613bc1565b835190830190613810818360208801613bc1565b01949350505050565b6000835161382b818460208801613bc1565b83519083019061383f818360208801613bc1565b652f6d6574612f60d01b9101908152600601949350505050565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906112869083018461376e565b600060018060a01b03808816835260a060208401526138ae60a084018861376e565b83810360408501526138c0818861376e565b95821660608501525092909216608090910152509392505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b602081526000610d00602083018461376e565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252601690820152751d1bdad95b905cdcda59db9b595b9d10dbdb9d1c9bdb60521b604082015260600190565b60208082526030908201527f546869732063616c6c206f6e6c7920776f726b73207768656e207472616e736660408201526f32b9399030b9329032b730b13632b21760811b606082015260800190565b60208082526036908201527f746f6b656e41737369676e6d656e74436f6e74726f6c206b65792072657175696040820152753932b2103337b9103a3434b990333ab731ba34b7b71760511b606082015260800190565b6020808252600b908201526a1cda1bdc10dbdb9d1c9bdb60aa1b604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6020808252602b908201527f73686f70436f6e74726f6c206b657920726571756972656420666f722074686960408201526a3990333ab731ba34b7b71760a91b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715613b2f57613b2f613c83565b604052919050565b600067ffffffffffffffff821115613b5157613b51613c83565b50601f01601f191660200190565b60008219821115613b7257613b72613c57565b500190565b600082613b8657613b86613c6d565b500490565b6000816000190483118215151615613ba557613ba5613c57565b500290565b600082821015613bbc57613bbc613c57565b500390565b60005b83811015613bdc578181015183820152602001613bc4565b838111156117975750506000910152565b600181811c90821680613c0157607f821691505b60208210811415613c2257634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415613c3c57613c3c613c57565b5060010190565b600082613c5257613c52613c6d565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114613cae57600080fd5b50565b8015158114613cae57600080fd5b6001600160e01b031981168114613cae57600080fdfea2646970667358221220faea0031cc4793c3b8fd1d99c1eab3a217c7ed78202a71e6c539f71766c8fe1764736f6c634300080400330000000000000000000000000884fc15e31b1b634732e140cb3f94b3cbfdd1c50000000000000000000000000000000000000000000000000000000000000064000000000000000000000000a86949e286bf3c2ffd2327b2ffc5a12b63c1ccb9
Deployed Bytecode
0x6080604052600436106102515760003560e01c80635c6f926911610139578063a22cb465116100b6578063c543e0fe1161007a578063c543e0fe146106c3578063c86cde8a146106e3578063c87b56dd14610703578063dd48f77414610723578063e985e9c514610743578063f36291dc1461078c57600080fd5b8063a22cb4651461062e578063a2dc49db1461064e578063accd00601461066e578063b7ec20861461068e578063b88d4fde146106a357600080fd5b806371f03793116100fd57806371f037931461059957806389b4ac04146105b95780638e8fa11f146105d957806391b7f5ed146105f957806395d89b411461061957600080fd5b80635c6f9269146105045780635ef935ee146105245780636352211e146105445780636c0360eb1461056457806370a082311461057957600080fd5b80632f745c59116101d25780634cd412d5116101965780634cd412d51461044f5780634f558e79146104645780634f6ccce71461048457806350029195146104a457806353a1397c146104b757806353cdef02146104e457600080fd5b80632f745c59146103b957806342842e0e146103d957806342966c68146103f95780634707d000146104195780634a1bb6b41461043957600080fd5b80630f574625116102195780630f5746251461031a5780631698befa1461033a57806318160ddd1461035a57806323b872dd146103795780632481bb5c1461039957600080fd5b806301ffc9a71461025657806306fdde031461028b578063081812fc146102ad57806308c6dc30146102e5578063095ea7b3146102f8575b600080fd5b34801561026257600080fd5b5061027661027136600461365d565b6107bc565b60405190151581526020015b60405180910390f35b34801561029757600080fd5b506102a06107e7565b604051610282919061390a565b3480156102b957600080fd5b506102cd6102c83660046136ff565b610879565b6040516001600160a01b039091168152602001610282565b6102cd6102f3366004613262565b610906565b34801561030457600080fd5b50610318610313366004613538565b610b37565b005b34801561032657600080fd5b50610318610335366004613717565b610c4d565b34801561034657600080fd5b5061027661035536600461330e565b610ceb565b34801561036657600080fd5b506008545b604051908152602001610282565b34801561038557600080fd5b50610318610394366004613346565b610d07565b3480156103a557600080fd5b50600a546102cd906001600160a01b031681565b3480156103c557600080fd5b5061036b6103d4366004613538565b610d38565b3480156103e557600080fd5b506103186103f4366004613346565b610dce565b34801561040557600080fd5b506103186104143660046136ff565b610de9565b34801561042557600080fd5b5061031861043436600461330e565b610f80565b34801561044557600080fd5b5061036b600b5481565b34801561045b57600080fd5b5061027661112d565b34801561047057600080fd5b5061027661047f3660046136ff565b6111ca565b34801561049057600080fd5b5061036b61049f3660046136ff565b6111d5565b6102cd6104b236600461349d565b611276565b3480156104c357600080fd5b5061036b6104d236600461322a565b600e6020526000908152604090205481565b3480156104f057600080fd5b506103186104ff36600461322a565b611290565b34801561051057600080fd5b506102cd61051f366004613538565b61140c565b34801561053057600080fd5b506102cd61053f3660046136ff565b61141e565b34801561055057600080fd5b506102cd61055f3660046136ff565b61147b565b34801561057057600080fd5b506102a06114f2565b34801561058557600080fd5b5061036b61059436600461322a565b611501565b3480156105a557600080fd5b506103186105b4366004613717565b611588565b3480156105c557600080fd5b506103186105d4366004613563565b6115fa565b3480156105e557600080fd5b506103186105f436600461341d565b61179d565b34801561060557600080fd5b506103186106143660046136ff565b611921565b34801561062557600080fd5b506102a0611a6e565b34801561063a57600080fd5b506103186106493660046133f0565b611a7d565b34801561065a57600080fd5b50600d546102cd906001600160a01b031681565b34801561067a57600080fd5b5061027661068936600461322a565b611b42565b34801561069a57600080fd5b5061036b611b56565b3480156106af57600080fd5b506103186106be366004613386565b611c7e565b3480156106cf57600080fd5b506102cd6106de36600461322a565b611cb0565b3480156106ef57600080fd5b5061036b6106fe36600461322a565b611cc4565b34801561070f57600080fd5b506102a061071e3660046136ff565b611d25565b34801561072f57600080fd5b5061031861073e36600461330e565b611def565b34801561074f57600080fd5b5061027661075e36600461330e565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b34801561079857600080fd5b506102766107a736600461322a565b600c6020526000908152604090205460ff1681565b60006001600160e01b0319821663780e9d6360e01b14806107e157506107e182611f03565b92915050565b6060600080546107f690613bed565b80601f016020809104026020016040519081016040528092919081815260200182805461082290613bed565b801561086f5780601f106108445761010080835404028352916020019161086f565b820191906000526020600020905b81548152906001019060200180831161085257829003601f168201915b5050505050905090565b600061088482611f53565b6108ea5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600080610911611b56565b336000908152600c602052604090205490915060ff16806109d95750600a5460405163bf40fac160e01b815260206004820152600b60248201526a3a37b5b2b72437b63232b960a91b60448201526001600160a01b039091169063bf40fac19060640160206040518083038186803b15801561098c57600080fd5b505afa1580156109a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c49190613246565b6001600160a01b0316336001600160a01b0316145b156109e2575060005b80341015610a495760405162461bcd60e51b815260206004820152602e60248201527f596f75206e65656420746f2073656e64206d6f6e657920746f2063726561746560448201526d10309031b7b63632b1ba34b7b71760911b60648201526084016108e1565b6000610a59898989898989611f70565b600a5460405163bf40fac160e01b815260206004820152600b60248201526a62656e656669636961727960a81b6044820152919250610b069184916001600160a01b03169063bf40fac19060640160206040518083038186803b158015610abf57600080fd5b505afa158015610ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af79190613246565b6001600160a01b0316906120e1565b81341115610b2b57610b2b610b1b8334613baa565b6001600160a01b038b16906120e1565b98975050505050505050565b6000610b428261147b565b9050806001600160a01b0316836001600160a01b03161415610bb05760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084016108e1565b336001600160a01b0382161480610bcc5750610bcc813361075e565b610c3e5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c000000000000000060648201526084016108e1565b610c4883836121fa565b505050565b610c5561112d565b1515600114610c765760405162461bcd60e51b81526004016108e19061399f565b6000610c818461147b565b6001600160a01b0381166000908152600e602090815260408083205490519394509192610cbf923092630f57462560e01b92339288928c920161379a565b604051602081830303815290604052805190602001209050610ce48282878787612268565b5050505050565b6000610d00836001600160a01b0384166123fd565b9392505050565b610d1133826123fd565b610d2d5760405162461bcd60e51b81526004016108e190613a6a565b610c488383836124e7565b6000610d4383611501565b8210610da55760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016108e1565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b610c4883838360405180602001604052806000815250611c7e565b806001600160a01b0381163314610e595760405162461bcd60e51b815260206004820152602e60248201527f4f6e6c792074686520636f6c6c656374696f6e20697473656c662063616e206260448201526d3ab937103a3432903a37b5b2b71760911b60648201526084016108e1565b806001600160a01b03166355c857fe6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e9257600080fd5b505afa158015610ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eca9190613645565b15610f255760405162461bcd60e51b815260206004820152602560248201527f4f6e6c7920656d70747920636f6c6c656374696f6e732063616e206265206275604482015264393732b21760d91b60648201526084016108e1565b6000610f308361147b565b9050610f3b83612692565b6040516001600160a01b0383811682528216907fe234f7a6922ece586c80e5ffab3cbc7b8a57d40e8b86753d858ee5bd25efebf39060200160405180910390a2505050565b600a5460405163bf40fac160e01b81526001600160a01b039091169063bf40fac190610fae9060040161396f565b60206040518083038186803b158015610fc657600080fd5b505afa158015610fda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ffe9190613246565b6001600160a01b0316336001600160a01b03161461102e5760405162461bcd60e51b81526004016108e1906139ef565b6040516370a0823160e01b81523060048201526001600160a01b0383169063a9059cbb90839083906370a082319060240160206040518083038186803b15801561107757600080fd5b505afa15801561108b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110af9190613645565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b1580156110f557600080fd5b505af1158015611109573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c489190613629565b600080600a60009054906101000a90046001600160a01b03166001600160a01b031663a564a2e06040518163ffffffff1660e01b815260040160206040518083038186803b15801561117e57600080fd5b505afa158015611192573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b69190613645565b90508015806111c457504281115b91505090565b60006107e182611f53565b60006111e060085490565b82106112435760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b60648201526084016108e1565b6008828154811061126457634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b6000611286338787878787610906565b9695505050505050565b600a5460405163bf40fac160e01b81526001600160a01b039091169063bf40fac1906112be90600401613a45565b60206040518083038186803b1580156112d657600080fd5b505afa1580156112ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130e9190613246565b6001600160a01b0316336001600160a01b03161461133e5760405162461bcd60e51b81526004016108e190613abb565b6001600160a01b0381166113b05760405162461bcd60e51b815260206004820152603360248201527f596f75206e65656420746f2070726f7669646520616e2061637475616c20627260448201527234b233b2903230ba309031b7b73a3930b1ba1760691b60648201526084016108e1565b600a546040516001600160a01b038084169216907f6a6e057f21cc834cf349d8150e92867f52cb34d54375f174c09c431538c3dfb990600090a3600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6000610d0061141b8484610d38565b90565b600061142982611f53565b6114755760405162461bcd60e51b815260206004820152601a60248201527f436f6c6c656374696f6e206e6565647320746f2065786973742e00000000000060448201526064016108e1565b816107e1565b6000818152600260205260408120546001600160a01b0316806107e15760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b60648201526084016108e1565b60606114fc612739565b905090565b60006001600160a01b03821661156c5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b60648201526084016108e1565b506001600160a01b031660009081526003602052604090205490565b61159061112d565b15156001146115b15760405162461bcd60e51b81526004016108e19061399f565b60006115bc8461147b565b6001600160a01b0381166000908152600e602090815260408083205490519394509192610cbf9230926371f0379360e01b9287928a928c920161379a565b600a5460405163bf40fac160e01b81526001600160a01b039091169063bf40fac19061162890600401613a45565b60206040518083038186803b15801561164057600080fd5b505afa158015611654573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116789190613246565b6001600160a01b0316336001600160a01b0316146116a85760405162461bcd60e51b81526004016108e190613abb565b815160005b818110156117975782600c60008684815181106116da57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555083818151811061173957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03167fef831a7da9050b3ebdfc86f7ecf0268d61828bd15ebcfe20611cb09f55e8f3088460405161177d911515815260200190565b60405180910390a28061178f81613c28565b9150506116ad565b50505050565b600a5460405163bf40fac160e01b81526001600160a01b039091169063bf40fac1906117cb9060040161396f565b60206040518083038186803b1580156117e357600080fd5b505afa1580156117f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181b9190613246565b6001600160a01b0316336001600160a01b03161461184b5760405162461bcd60e51b81526004016108e1906139ef565b6001600160a01b0383166118a15760405162461bcd60e51b815260206004820152601e60248201527f6e65656420612076616c6964207265766572736520726567697374726172000060448201526064016108e1565b60405163c47f002760e01b81526001600160a01b0384169063c47f0027906118cf90859085906004016138db565b602060405180830381600087803b1580156118e957600080fd5b505af11580156118fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117979190613645565b600a5460405163bf40fac160e01b81526001600160a01b039091169063bf40fac19061194f90600401613a45565b60206040518083038186803b15801561196757600080fd5b505afa15801561197b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061199f9190613246565b6001600160a01b0316336001600160a01b0316146119cf5760405162461bcd60e51b81526004016108e190613abb565b60008111611a2d5760405162461bcd60e51b815260206004820152602560248201527f596f75206e65656420746f2070726f766964652061206e6f6e2d7a65726f20706044820152643934b1b29760d91b60648201526084016108e1565b600b5460408051918252602082018390527f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68910160405180910390a1600b55565b6060600180546107f690613bed565b6001600160a01b038216331415611ad65760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016108e1565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60006107e16001600160a01b038316611f53565b600a5460405163bf40fac160e01b81526020600482015260066024820152654f7261636c6560d01b60448201526000916064916001600160a01b039091169063bf40fac190830160206040518083038186803b158015611bb557600080fd5b505afa158015611bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bed9190613246565b60405163048cc1a760e51b8152600060048201526001600160a01b03919091169063919834e09060240160206040518083038186803b158015611c2f57600080fd5b505afa158015611c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c679190613645565b600b54611c749190613b8b565b6114fc9190613b77565b611c8833836123fd565b611ca45760405162461bcd60e51b81526004016108e190613a6a565b611797848484846127e7565b60006107e16001600160a01b03831661147b565b60006001600160a01b038216611cd981611f53565b6107e15760405162461bcd60e51b815260206004820152601a60248201527f436f6c6c656374696f6e206e6565647320746f2065786973742e00000000000060448201526064016108e1565b6060611d3082611f53565b611d945760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b60648201526084016108e1565b6000611d9e612739565b90506000815111611dbe5760405180602001604052806000815250610d00565b80611dc88461281a565b604051602001611dd99291906137ea565b6040516020818303038152906040529392505050565b600a5460405163bf40fac160e01b81526001600160a01b039091169063bf40fac190611e1d9060040161396f565b60206040518083038186803b158015611e3557600080fd5b505afa158015611e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6d9190613246565b6001600160a01b0316336001600160a01b031614611e9d5760405162461bcd60e51b81526004016108e1906139ef565b60405163a22cb46560e01b81526001600160a01b0382811660048301526001602483015283169063a22cb46590604401600060405180830381600087803b158015611ee757600080fd5b505af1158015611efb573d6000803e3d6000fd5b505050505050565b60006001600160e01b031982166380ac58cd60e01b1480611f3457506001600160e01b03198216635b5e139f60e01b145b806107e157506301ffc9a760e01b6001600160e01b03198316146107e1565b6000908152600260205260409020546001600160a01b0316151590565b600d546000906001600160a01b0316611fd55760405162461bcd60e51b815260206004820152602160248201527f536574206120636f6c6c656374696f6e2070726f746f747970652066697273746044820152602160f81b60648201526084016108e1565b8451600090156120045785516020870120600d54611ffc906001600160a01b031682612934565b91505061201c565b600d54612019906001600160a01b03166129d4565b90505b6040516001600160a01b0382811682528916907f5b84d9550adb7000df7bee717735ecd3af48ea3f66c6886d52e8227548fb228c9060200160405180910390a261206f886001600160a01b038316612a71565b604051632337dc9b60e21b81526001600160a01b03821690638cdf726c906120a3908a908a908a908a908a9060040161388c565b600060405180830381600087803b1580156120bd57600080fd5b505af11580156120d1573d6000803e3d6000fd5b50929a9950505050505050505050565b804710156121315760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016108e1565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461217e576040519150601f19603f3d011682016040523d82523d6000602084013e612183565b606091505b5050905080610c485760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016108e1565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061222f8261147b565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006122c1856040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b905060006122cf8284612a8f565b9050866001600160a01b0316816001600160a01b0316146123585760405162461bcd60e51b815260206004820152603e60248201527f5369676e6174757265206e6565647320746f206d6174636820706172616d657460448201527f6572732c206e6f6e63652c20616e642063757272656e74206f776e65722e000060648201526084016108e1565b6001600160a01b038781166000818152600e6020908152604091829020548251338152918201528893881692917fba05f551fcc429cba611372aa0055e3573f26273f66d1a48bdb5b4f7896bf022910160405180910390a46001600160a01b0387166000908152600e602052604081208054916123d483613c28565b91905055506123f4878587604051806020016040528060008152506127e7565b50505050505050565b600061240882611f53565b6124695760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084016108e1565b60006124748361147b565b9050806001600160a01b0316846001600160a01b031614806124af5750836001600160a01b03166124a484610879565b6001600160a01b0316145b806124df57506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b03166124fa8261147b565b6001600160a01b0316146125625760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b60648201526084016108e1565b6001600160a01b0382166125c45760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016108e1565b6125cf838383612b00565b6125da6000826121fa565b6001600160a01b0383166000908152600360205260408120805460019290612603908490613baa565b90915550506001600160a01b0382166000908152600360205260408120805460019290612631908490613b5f565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061269d8261147b565b90506126ab81600084612b00565b6126b66000836121fa565b6001600160a01b03811660009081526003602052604081208054600192906126df908490613baa565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b600a546040805163261220a360e01b815290516060926001600160a01b03169163261220a3916004808301926000929190829003018186803b15801561277e57600080fd5b505afa158015612792573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127ba9190810190613695565b6127c2611a6e565b6040516020016127d3929190613819565b604051602081830303815290604052905090565b6127f28484846124e7565b6127fe84848484612b34565b6117975760405162461bcd60e51b81526004016108e19061391d565b60608161283e5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612868578061285281613c28565b91506128619050600a83613b77565b9150612842565b60008167ffffffffffffffff81111561289157634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156128bb576020820181803683370190505b5090505b84156124df576128d0600183613baa565b91506128dd600a86613c43565b6128e8906030613b5f565b60f81b81838151811061290b57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535061292d600a86613b77565b94506128bf565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152826037826000f59150506001600160a01b0381166107e15760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c656400000000000000000060448201526064016108e1565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528260601b60148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f09150506001600160a01b038116612a6c5760405162461bcd60e51b8152602060048201526016602482015275115490cc4c4d8dce8818dc99585d194819985a5b195960521b60448201526064016108e1565b919050565b612a8b828260405180602001604052806000815250612c41565b5050565b60008151604114612ae25760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016108e1565b60208201516040830151606084015160001a61128686828585612c74565b612b0861112d565b1515600114612b295760405162461bcd60e51b81526004016108e19061399f565b610c48838383612e1d565b60006001600160a01b0384163b15612c3657604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612b78903390899088908890600401613859565b602060405180830381600087803b158015612b9257600080fd5b505af1925050508015612bc2575060408051601f3d908101601f19168201909252612bbf91810190613679565b60015b612c1c573d808015612bf0576040519150601f19603f3d011682016040523d82523d6000602084013e612bf5565b606091505b508051612c145760405162461bcd60e51b81526004016108e19061391d565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506124df565b506001949350505050565b612c4b8383612ed5565b612c586000848484612b34565b610c485760405162461bcd60e51b81526004016108e19061391d565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612cf15760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016108e1565b8360ff16601b1480612d0657508360ff16601c145b612d5d5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016108e1565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015612db1573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612e145760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016108e1565b95945050505050565b6001600160a01b038316612e7857612e7381600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b612e9b565b816001600160a01b0316836001600160a01b031614612e9b57612e9b8382613014565b6001600160a01b038216612eb257610c48816130b1565b826001600160a01b0316826001600160a01b031614610c4857610c48828261318a565b6001600160a01b038216612f2b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016108e1565b612f3481611f53565b15612f815760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016108e1565b612f8d60008383612b00565b6001600160a01b0382166000908152600360205260408120805460019290612fb6908490613b5f565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000600161302184611501565b61302b9190613baa565b60008381526007602052604090205490915080821461307e576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b6008546000906130c390600190613baa565b600083815260096020526040812054600880549394509092849081106130f957634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050806008838154811061312857634e487b7160e01b600052603260045260246000fd5b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061316e57634e487b7160e01b600052603160045260246000fd5b6001900381819060005260206000200160009055905550505050565b600061319583611501565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b8035612a6c81613cb1565b600082601f8301126131e9578081fd5b81356131fc6131f782613b37565b613b06565b818152846020838601011115613210578283fd5b816020850160208301379081016020019190915292915050565b60006020828403121561323b578081fd5b8135610d0081613c99565b600060208284031215613257578081fd5b8151610d0081613c99565b60008060008060008060c0878903121561327a578182fd5b863561328581613c99565b9550602087013561329581613c99565b9450604087013567ffffffffffffffff808211156132b1578384fd5b6132bd8a838b016131d9565b955060608901359150808211156132d2578384fd5b506132df89828a016131d9565b93505060808701356132f081613c99565b915060a087013561330081613c99565b809150509295509295509295565b60008060408385031215613320578182fd5b823561332b81613c99565b9150602083013561333b81613c99565b809150509250929050565b60008060006060848603121561335a578283fd5b833561336581613c99565b9250602084013561337581613c99565b929592945050506040919091013590565b6000806000806080858703121561339b578182fd5b84356133a681613c99565b935060208501356133b681613c99565b925060408501359150606085013567ffffffffffffffff8111156133d8578182fd5b6133e4878288016131d9565b91505092959194509250565b60008060408385031215613402578182fd5b823561340d81613c99565b9150602083013561333b81613cb1565b600080600060408486031215613431578081fd5b833561343c81613c99565b9250602084013567ffffffffffffffff80821115613458578283fd5b818601915086601f83011261346b578283fd5b813581811115613479578384fd5b87602082850101111561348a578384fd5b6020830194508093505050509250925092565b600080600080600060a086880312156134b4578283fd5b85356134bf81613c99565b9450602086013567ffffffffffffffff808211156134db578485fd5b6134e789838a016131d9565b955060408801359150808211156134fc578485fd5b50613509888289016131d9565b935050606086013561351a81613c99565b9150608086013561352a81613c99565b809150509295509295909350565b6000806040838503121561354a578182fd5b823561355581613c99565b946020939093013593505050565b60008060408385031215613575578182fd5b823567ffffffffffffffff8082111561358c578384fd5b818501915085601f83011261359f578384fd5b81356020828211156135b3576135b3613c83565b8160051b92506135c4818401613b06565b8281528181019085830185870184018b10156135de578889fd5b8896505b8487101561360c57803595506135f786613c99565b858352600196909601959183019183016135e2565b50965061361c90508782016131ce565b9450505050509250929050565b60006020828403121561363a578081fd5b8151610d0081613cb1565b600060208284031215613656578081fd5b5051919050565b60006020828403121561366e578081fd5b8135610d0081613cbf565b60006020828403121561368a578081fd5b8151610d0081613cbf565b6000602082840312156136a6578081fd5b815167ffffffffffffffff8111156136bc578182fd5b8201601f810184136136cc578182fd5b80516136da6131f782613b37565b8181528560208385010111156136ee578384fd5b612e14826020830160208601613bc1565b600060208284031215613710578081fd5b5035919050565b60008060006060848603121561372b578081fd5b83359250602084013561373d81613c99565b9150604084013567ffffffffffffffff811115613758578182fd5b613764868287016131d9565b9150509250925092565b60008151808452613786816020860160208601613bc1565b601f01601f19169290920160200192915050565b6bffffffffffffffffffffffff19606097881b811682526001600160e01b031996909616601482015293861b8516601885015291851b909316602c83015260408201929092529182015260800190565b600083516137fc818460208801613bc1565b835190830190613810818360208801613bc1565b01949350505050565b6000835161382b818460208801613bc1565b83519083019061383f818360208801613bc1565b652f6d6574612f60d01b9101908152600601949350505050565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906112869083018461376e565b600060018060a01b03808816835260a060208401526138ae60a084018861376e565b83810360408501526138c0818861376e565b95821660608501525092909216608090910152509392505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b602081526000610d00602083018461376e565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252601690820152751d1bdad95b905cdcda59db9b595b9d10dbdb9d1c9bdb60521b604082015260600190565b60208082526030908201527f546869732063616c6c206f6e6c7920776f726b73207768656e207472616e736660408201526f32b9399030b9329032b730b13632b21760811b606082015260800190565b60208082526036908201527f746f6b656e41737369676e6d656e74436f6e74726f6c206b65792072657175696040820152753932b2103337b9103a3434b990333ab731ba34b7b71760511b606082015260800190565b6020808252600b908201526a1cda1bdc10dbdb9d1c9bdb60aa1b604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6020808252602b908201527f73686f70436f6e74726f6c206b657920726571756972656420666f722074686960408201526a3990333ab731ba34b7b71760a91b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715613b2f57613b2f613c83565b604052919050565b600067ffffffffffffffff821115613b5157613b51613c83565b50601f01601f191660200190565b60008219821115613b7257613b72613c57565b500190565b600082613b8657613b86613c6d565b500490565b6000816000190483118215151615613ba557613ba5613c57565b500290565b600082821015613bbc57613bbc613c57565b500390565b60005b83811015613bdc578181015183820152602001613bc4565b838111156117975750506000910152565b600181811c90821680613c0157607f821691505b60208210811415613c2257634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415613c3c57613c3c613c57565b5060010190565b600082613c5257613c52613c6d565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114613cae57600080fd5b50565b8015158114613cae57600080fd5b6001600160e01b031981168114613cae57600080fdfea2646970667358221220faea0031cc4793c3b8fd1d99c1eab3a217c7ed78202a71e6c539f71766c8fe1764736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000884fc15e31b1b634732e140cb3f94b3cbfdd1c50000000000000000000000000000000000000000000000000000000000000064000000000000000000000000a86949e286bf3c2ffd2327b2ffc5a12b63c1ccb9
-----Decoded View---------------
Arg [0] : _bridgeDataAddress (address): 0x0884fc15E31B1B634732e140cb3F94b3cbFdD1c5
Arg [1] : _priceEurCent (uint256): 100
Arg [2] : _collectionPrototypeAddress (address): 0xa86949e286BF3c2FFD2327b2ffC5A12B63c1CcB9
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000884fc15e31b1b634732e140cb3f94b3cbfdd1c5
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [2] : 000000000000000000000000a86949e286bf3c2ffd2327b2ffc5a12b63c1ccb9
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$13.50
Net Worth in XDAI
Token Allocations
DAI
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $0.999352 | 13.5083 | $13.5 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.