Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ERC721StorageLayer
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Unlicense // Creator: 0xYeety/YEETY.eth - CTO, Virtue Labs pragma solidity ^0.8.17; import "lib/openzeppelin-contracts/contracts/access/Ownable.sol"; import "lib/openzeppelin-contracts/contracts/utils/Address.sol"; import "lib/openzeppelin-contracts/contracts/utils/Strings.sol"; import "lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol"; import "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; /*********************************************************************************************************************/ /* ___ ___ ___ ___ ___ ___ ___ */ /* /\ \ /\__\ ___ /\__\ /\ \ /\ \ /\__\ /\ \ */ /* /::\ \ /:/ / /\ \ /:/ / /::\ \ \:\ \ /:/ / /::\ \ */ /* /:/\:\ \ /:/ / \:\ \ /:/ / /:/\:\ \ \:\ \ /:/__/ /:/\:\ \ */ /* /::\~\:\__\ /:/ / ___ /::\__\ /:/ / /:/ \:\__\ /::\ \ /::\ \ ___ /::\~\:\ \ */ /* /:/\:\ \:|__| /:/__/ /\__\ __/:/\/__/ /:/__/ /:/__/ \:|__| /:/\:\__\ /:/\:\ /\__\ /:/\:\ \:\__\ */ /* \:\~\:\/:/ / \:\ \ /:/ / /\/:/ / \:\ \ \:\ \ /:/ / /:/ \/__/ \/__\:\/:/ / \:\~\:\ \/__/ */ /* \:\ \::/ / \:\ /:/ / \::/__/ \:\ \ \:\ /:/ / /:/ / \::/ / \:\ \:\__\ */ /* \:\/:/ / \:\/:/ / \:\__\ \:\ \ \:\/:/ / \/__/ /:/ / \:\ \/__/ */ /* \::/__/ \::/ / \/__/ \:\__\ \::/__/ /:/ / \:\__\ */ /* ~~ \/__/ \/__/ ~~ \/__/ \/__/ */ /* */ /* ___ ___ ___ ___ ___ ___ ___ ___ */ /* /\ \ /\__\ /\ \ /\ \ /\ \ /\ \ /\ \ /\__\ */ /* /::\ \ /:/ / /::\ \ \:\ \ /::\ \ /::\ \ /::\ \ /::| | */ /* /:/\:\ \ /:/ / /:/\:\ \ \:\ \ /:/\:\ \ /:/\:\ \ /:/\:\ \ /:|:| | */ /* /::\~\:\ \ /:/ / /::\~\:\ \ /::\ \ /::\~\:\ \ /:/ \:\ \ /::\~\:\ \ /:/|:|__|__ */ /* /:/\:\ \:\__\ /:/__/ /:/\:\ \:\__\ /:/\:\__\ /:/\:\ \:\__\ /:/__/ \:\__\ /:/\:\ \:\__\ /:/ |::::\__\ */ /* \/__\:\/:/ / \:\ \ \/__\:\/:/ / /:/ \/__/ \/__\:\ \/__/ \:\ \ /:/ / \/_|::\/:/ / \/__/~~/:/ / */ /* \::/ / \:\ \ \::/ / /:/ / \:\__\ \:\ /:/ / |:|::/ / /:/ / */ /* \/__/ \:\ \ /:/ / \/__/ \/__/ \:\/:/ / |:|\/__/ /:/ / */ /* \:\__\ /:/ / \::/ / |:| | /:/ / */ /* \/__/ \/__/ \/__/ \|__| \/__/ */ /*********************************************************************************************************************/ contract ERC721StorageLayer is Ownable { using Address for address; using Strings for uint256; ////////// mapping(uint256 => address) private registeredContracts; mapping(address => uint256) private contractNumberings; mapping(address => bool) private isRegistered; uint256 numRegistered; modifier onlyRegistered() { _isRegistered(); _; } function _isRegistered() internal view virtual { require(isRegistered[msg.sender], "r"); } mapping(address => string) private _contractNames; mapping(address => string) private _contractSymbols; bool public canSetNameAndSymbol = true; mapping(address => string) private _contractDescriptions; mapping(address => string) private _contractImages; ////////// address public mintingContract; modifier onlyMintingContract() { _isMintingContract(); _; } function _isMintingContract() internal view virtual { require(msg.sender == mintingContract, "m"); } ////////// uint256 currentIndex; mapping(uint256 => address) _ownerships; mapping(address => uint256) _balances; address public immutable burnAddress = 0x000000000000000000000000000000000000dEaD; mapping(address => uint256) private _burnCounts; ////////// mapping(uint256 => address) private _tokenApprovals; mapping(address => mapping(address => mapping(address => bool))) private _operatorApprovals; //////////////////// function registerTopLevel( string memory name_, string memory symbol_, string memory description_, string memory image_ ) public { require(numRegistered < 5, "mr"); require(tx.origin == owner(), "a"); registeredContracts[numRegistered] = msg.sender; contractNumberings[msg.sender] = numRegistered; _contractNames[msg.sender] = name_; _contractSymbols[msg.sender] = symbol_; _contractDescriptions[msg.sender] = description_; _contractImages[msg.sender] = image_; isRegistered[msg.sender] = true; numRegistered++; } function registerMintingContract() public { require(tx.origin == owner(), "a"); mintingContract = msg.sender; } ////////// function storage_totalSupply(address collection) public view returns (uint256) { require(isRegistered[collection], "r"); return (currentIndex/5) - _burnCounts[collection]; } function storage_tokenByIndex( address collection, uint256 index ) public view returns (uint256) { require(isRegistered[collection], "r"); require(index < (currentIndex/5), "g"); require(storage_ownerOf(collection, index) != burnAddress, "b"); return index; } function storage_tokenOfOwnerByIndex( address collection, address owner, uint256 index ) public view returns (uint256) { require(isRegistered[collection], "r"); require(index < storage_balanceOf(collection, owner), "b"); uint256 numTokenIds = currentIndex; uint256 tokenIdsIdx = 0; address currOwnershipAddr = address(0); uint256 j; uint256 offset = contractNumberings[collection]; for (uint256 i = 0; i < numTokenIds/5; i++) { j = i*5 + offset; address ownership = _ownerships[j]; if (ownership != address(0)) { currOwnershipAddr = ownership; } if (currOwnershipAddr == owner) { if (tokenIdsIdx == index) { return i; } tokenIdsIdx++; } } revert("u"); } function storage_tokenOfOwnerByIndexStepped( address collection, address owner, uint256 index, uint256 lastToken, uint256 lastIndex ) public view returns (uint256) { require(isRegistered[collection], "r"); require(index < storage_balanceOf(collection, owner), "b"); uint256 numTokenIds = currentIndex; uint256 tokenIdsIdx = ((lastIndex == 0) ? 0 : (lastIndex + 1)); address currOwnershipAddr = address(0); uint256 j; uint256 offset = contractNumberings[collection]; for (uint256 i = ((lastToken == 0) ? 0 : (lastToken + 1)); i < numTokenIds/5; i++) { j = i*5 + offset; address ownership = _ownerships[j]; if (ownership != address(0)) { currOwnershipAddr = ownership; } if (currOwnershipAddr == owner) { if (tokenIdsIdx == index) { return i; } tokenIdsIdx++; } } revert("u"); } function storage_balanceOf( address collection, address owner ) public view returns (uint256) { require(isRegistered[collection], "r"); require(owner != address(0) || owner != burnAddress, "0/burn"); return (_balances[owner] >> (14*contractNumberings[collection]))%(1<<14); } function storage_ownerOf( address collection, uint256 tokenId ) public view returns (address) { require(isRegistered[collection], "r"); require(tokenId < currentIndex/5, "t"); uint256 offset = contractNumberings[collection]; for (uint256 i = tokenId*5 + offset; i >= 0; i--) { address ownership = _ownerships[i]; if (ownership != address(0)) { return ownership; } } revert("o"); } function storage_name(address collection) public view returns (string memory) { require(isRegistered[collection], "r"); return _contractNames[collection]; } function storage_setName(address collection, string memory newName) public onlyOwner { require(isRegistered[collection] && canSetNameAndSymbol, "r/cs"); _contractNames[collection] = newName; } function storage_symbol(address collection) public view returns (string memory) { require(isRegistered[collection] && canSetNameAndSymbol, "r/cs"); return _contractSymbols[collection]; } function storage_setSymbol(address collection, string memory newSymbol) public onlyOwner { require(isRegistered[collection], "r"); _contractSymbols[collection] = newSymbol; } function flipCanSetNameAndSymbol() public onlyOwner { require(canSetNameAndSymbol, "cs"); canSetNameAndSymbol = false; } function storage_setDescription( address collection, string memory newDescription ) public onlyOwner { require(isRegistered[collection], "r"); _contractDescriptions[collection] = newDescription; } function storage_setImage( address collection, string memory newImage ) public onlyOwner { require(isRegistered[collection], "r"); _contractImages[collection] = newImage; } function storage_approve(address msgSender, address to, uint256 tokenId) public onlyRegistered { address owner = ERC721StorageLayer.storage_ownerOf(msg.sender, tokenId); require(to != owner, "o"); require( msgSender == owner || storage_isApprovedForAll(msg.sender, owner, msgSender), "a" ); _approve(to, tokenId*5 + contractNumberings[msg.sender], owner); } function storage_getApproved( address collection, uint256 tokenId ) public view returns (address) { require(isRegistered[collection], "r"); uint256 mappedTokenId = tokenId*5 + contractNumberings[collection]; require(_exists(mappedTokenId, tokenId), "a"); return _tokenApprovals[mappedTokenId]; } function storage_setApprovalForAll( address msgSender, address operator, bool approved ) public onlyRegistered { require(operator != msgSender, "a"); _operatorApprovals[msg.sender][msgSender][operator] = approved; ERC721TopLevelProto(msg.sender).emitApprovalForAll(msgSender, operator, approved); } function storage_globalSetApprovalForAll( address operator, bool approved ) public { require(operator != msg.sender, "a"); for (uint256 i = 0; i < 5; i++) { address topLevelContract = registeredContracts[i]; require(!(ERC721TopLevelProto(topLevelContract).operatorRestrictions(operator)), "r"); _operatorApprovals[topLevelContract][msg.sender][operator] = approved; ERC721TopLevelProto(topLevelContract).emitApprovalForAll(msg.sender, operator, approved); } } function storage_isApprovedForAll( address collection, address owner, address operator ) public view returns (bool) { require(isRegistered[collection], "r"); return _operatorApprovals[collection][owner][operator]; } function storage_transferFrom( address msgSender, address from, address to, uint256 tokenId ) public onlyRegistered { _transfer(msgSender, from, to, tokenId*5 + contractNumberings[msg.sender]); ERC721TopLevelProto(msg.sender).emitTransfer(from, to, tokenId); } function storage_safeTransferFrom( address msgSender, address from, address to, uint256 tokenId ) public onlyRegistered { storage_safeTransferFrom(msgSender, from, to, tokenId, ""); } function storage_safeTransferFrom( address msgSender, address from, address to, uint256 tokenId, bytes memory _data ) public onlyRegistered { _transfer(msgSender, from, to, tokenId*5 + contractNumberings[msg.sender]); ERC721TopLevelProto(msg.sender).emitTransfer(from, to, tokenId); require( _checkOnERC721Received(msgSender, from, to, tokenId, _data), "z" ); } function storage_burnToken(address msgSender, uint256 tokenId) public onlyRegistered { _transfer( msgSender, storage_ownerOf(msg.sender, tokenId), burnAddress, tokenId*5 + contractNumberings[msg.sender] ); _burnCounts[msg.sender] += 1; ERC721TopLevelProto(msg.sender).emitTransfer(msgSender, burnAddress, tokenId); } function storage_exists( address collection, uint256 tokenId ) public view returns (bool) { require(isRegistered[collection], "r"); return _exists(tokenId*5 + contractNumberings[collection], tokenId); } function _exists(uint256 mappedTokenId, uint256 tokenId) private view returns (bool) { return (mappedTokenId < currentIndex && _ownerships[tokenId] != burnAddress); } function storage_safeMint( address msgSender, address to, uint256 quantity ) public onlyMintingContract { storage_safeMint(msgSender, to, quantity, ""); } function storage_safeMint( address msgSender, address to, uint256 quantity, bytes memory _data ) public onlyMintingContract { storage_mint(to, quantity); require(_checkOnERC721Received(msgSender, address(0), to, (currentIndex/5) - 1, _data), "z"); } function storage_mint(address to, uint256 quantity) private { uint256 startTokenId = currentIndex/5; require(to != address(0), "0"); // We know if the first token in the batch doesn't exist, the other ones don't as well, because of serial ordering. require(!_exists(currentIndex, startTokenId), "a"); uint256 balanceQtyAdd = 0; for (uint256 i = 0; i < 5; i++) { balanceQtyAdd += (quantity << (i*14)); } _balances[to] = _balances[to] + balanceQtyAdd; _ownerships[currentIndex] = to; uint256 updatedIndex = startTokenId; for (uint256 i = 0; i < quantity; i++) { for (uint256 j = 0; j < 5; j++) { ERC721TopLevelProto(registeredContracts[j]).emitTransfer(address(0), to, updatedIndex); } updatedIndex++; } currentIndex = updatedIndex*5; } function storage_contractURI(address collection) public view virtual returns (string memory) { require(isRegistered[collection], "r"); return string( abi.encodePacked( "data:application/json;utf8,{\"name\":\"", storage_name(collection), "\",", "\"description\":\"", _contractDescriptions[collection], "\",", "\"image\":\"", _contractImages[collection], "\",", "\"external_link\":\"https://crudeborne.wtf\",", "\"seller_fee_basis_points\":500,\"fee_recipient\":\"", uint256(uint160(mintingContract)).toHexString(), "\"}" ) ); } ////////// function _transfer( address msgSender, address from, address to, uint256 tokenId ) private { uint256 collectionTokenId = tokenId/5; address prevOwnership = storage_ownerOf(msg.sender, collectionTokenId); bool isApprovedOrOwner = (msgSender == prevOwnership || storage_getApproved(msg.sender, collectionTokenId) == msgSender || storage_isApprovedForAll(msg.sender, prevOwnership, msgSender)); require(isApprovedOrOwner && prevOwnership == from, "a"); require(prevOwnership == from, "o"); require(to != address(0), "0"); // Clear approvals from the previous owner _approve(address(0), tokenId, prevOwnership); _balances[from] -= (1 << (contractNumberings[msg.sender]*14)); _balances[to] += (1 << (contractNumberings[msg.sender]*14)); _ownerships[tokenId] = to; // If the ownership slot of tokenId+1 is not explicitly set, that means the transfer initiator owns it. // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls. uint256 nextTokenId = tokenId + 1; if (_ownerships[nextTokenId] == address(0)) { if (_exists(nextTokenId, nextTokenId/5)) { _ownerships[nextTokenId] = prevOwnership; } } } function _approve( address to, uint256 tokenId, address owner ) private { _tokenApprovals[tokenId] = to; ERC721TopLevelProto(msg.sender).emitApproval(owner, to, tokenId/5); } function _checkOnERC721Received( address msgSender, 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("z"); } else { assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } ////////// receive() external payable { (bool success, ) = payable(mintingContract).call{value: msg.value}(""); require(success, "F"); } function withdrawTokens(address tokenAddress) external onlyOwner { IERC20(tokenAddress).transfer(msg.sender, IERC20(tokenAddress).balanceOf(address(this))); } } //////////////////// abstract contract ERC721TopLevelProto { mapping(address => bool) public operatorRestrictions; function emitTransfer(address from, address to, uint256 tokenId) public virtual; function emitApproval(address owner, address approved, uint256 tokenId) public virtual; function emitApprovalForAll(address owner, address operator, bool approved) public virtual; } ////////////////////////////////////////
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @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 `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @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] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"burnAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"canSetNameAndSymbol","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flipCanSetNameAndSymbol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintingContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registerMintingContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"string","name":"description_","type":"string"},{"internalType":"string","name":"image_","type":"string"}],"name":"registerTopLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"storage_approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"storage_balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"storage_burnToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"storage_contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"storage_exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"storage_getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"storage_globalSetApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"storage_isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"storage_name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"storage_ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"storage_safeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"storage_safeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"storage_safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"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":"storage_safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"storage_setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"string","name":"newDescription","type":"string"}],"name":"storage_setDescription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"string","name":"newImage","type":"string"}],"name":"storage_setImage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"string","name":"newName","type":"string"}],"name":"storage_setName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"string","name":"newSymbol","type":"string"}],"name":"storage_setSymbol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"storage_symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"storage_tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"storage_tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"lastToken","type":"uint256"},{"internalType":"uint256","name":"lastIndex","type":"uint256"}],"name":"storage_tokenOfOwnerByIndexStepped","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"storage_totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"storage_transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040526007805460ff1916600117905561dead60805234801561002357600080fd5b5061002d33610032565b610082565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b608051612f23620000c16000396000818161049c01528181610ba50152818161112f01528181611ada01528181611b470152611f500152612f236000f3fe6080604052600436106102085760003560e01c80638da5cb5b11610118578063bac5ccc3116100a0578063e03313741161006f578063e03313741461069e578063e3712368146106b3578063e4999080146106d3578063f2fde38b146106f3578063fea6eb9e1461071357600080fd5b8063bac5ccc31461061e578063c240d9201461063e578063cfcc7e7a1461065e578063d2f6f67d1461067e57600080fd5b8063a6015db4116100e7578063a6015db414610589578063a9d2f455146105a9578063acb608b3146105c9578063b2238c9d146105de578063b4069dc8146105fe57600080fd5b80638da5cb5b1461050b57806391bd54f514610529578063962bf1f914610549578063a1601ad31461056957600080fd5b80632d53a1221161019b578063622574671161016a578063622574671461044a5780636bcfc62a1461046a57806370d5ae051461048a578063715018a6146104d65780637d706301146104eb57600080fd5b80632d53a122146103c0578063356bfa88146103e05780633dba0ac41461040057806349df728c1461042a57600080fd5b80631bd92142116101d75780631bd92142146103335780631ce102c614610353578063204d849a1461038057806321b24583146103a057600080fd5b806301b03a72146102a05780630d060ae0146102d35780631168132c146102f357806312f20cb51461031357600080fd5b3661029b57600a546040516000916001600160a01b03169034908381818185875af1925050503d806000811461025a576040519150601f19603f3d011682016040523d82523d6000602084013e61025f565b606091505b50509050806102995760405162461bcd60e51b81526020600482015260016024820152602360f91b60448201526064015b60405180910390fd5b005b600080fd5b3480156102ac57600080fd5b506102c06102bb3660046124ec565b610733565b6040519081526020015b60405180910390f35b3480156102df57600080fd5b506102996102ee3660046125dc565b6108bf565b3480156102ff57600080fd5b5061029961030e366004612638565b610926565b34801561031f57600080fd5b5061029961032e36600461267f565b610a02565b34801561033f57600080fd5b5061029961034e3660046126ca565b610a2c565b34801561035f57600080fd5b5061037361036e366004612706565b610a4f565b6040516102ca9190612771565b34801561038c57600080fd5b506102c061039b366004612784565b610b59565b3480156103ac57600080fd5b506103736103bb366004612706565b610c64565b3480156103cc57600080fd5b506102996103db3660046126ca565b610cc2565b3480156103ec57600080fd5b506102996103fb3660046125dc565b610d90565b34801561040c57600080fd5b5060075461041a9060ff1681565b60405190151581526020016102ca565b34801561043657600080fd5b50610299610445366004612706565b610df2565b34801561045657600080fd5b5061029961046536600461267f565b610edf565b34801561047657600080fd5b5061041a6104853660046127b7565b610f7a565b34801561049657600080fd5b506104be7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102ca565b3480156104e257600080fd5b50610299610fea565b3480156104f757600080fd5b506102996105063660046127e1565b610ffe565b34801561051757600080fd5b506000546001600160a01b03166104be565b34801561053557600080fd5b506102c06105443660046127b7565b6110b4565b34801561055557600080fd5b506102c06105643660046126ca565b61118d565b34801561057557600080fd5b5061029961058436600461285a565b6112b2565b34801561059557600080fd5b506102996105a43660046125dc565b6113dc565b3480156105b557600080fd5b5061041a6105c4366004612907565b611465565b3480156105d557600080fd5b506102996114d6565b3480156105ea57600080fd5b506102996105f936600461294a565b611514565b34801561060a57600080fd5b50610373610619366004612706565b61156a565b34801561062a57600080fd5b506102c0610639366004612706565b61160c565b34801561064a57600080fd5b506102996106593660046125dc565b611676565b34801561066a57600080fd5b506104be6106793660046127b7565b6116d8565b34801561068a57600080fd5b50600a546104be906001600160a01b031681565b3480156106aa57600080fd5b506102996117bf565b3480156106bf57600080fd5b506102996106ce3660046129a6565b61180a565b3480156106df57600080fd5b506104be6106ee3660046127b7565b61198c565b3480156106ff57600080fd5b5061029961070e366004612706565b611a39565b34801561071f57600080fd5b5061029961072e3660046127b7565b611ab2565b6001600160a01b03851660009081526003602052604081205460ff1661076b5760405162461bcd60e51b8152600401610290906129dd565b6107758686610b59565b84106107935760405162461bcd60e51b8152600401610290906129f8565b600b54600083156107ae576107a9846001612a29565b6107b1565b60005b6001600160a01b0389166000908152600260205260408120549192509081908188156107e7576107e2896001612a29565b6107ea565b60005b90505b6107f8600587612a52565b811015610889578161080b826005612a66565b6108159190612a29565b6000818152600c60205260409020549093506001600160a01b0316801561083a578094505b8b6001600160a01b0316856001600160a01b031603610876578a8603610868575095506108b6945050505050565b8561087281612a7d565b9650505b508061088181612a7d565b9150506107ed565b5060405162461bcd60e51b81526020600482015260016024820152607560f81b6044820152606401610290565b95945050505050565b6108c7611ba7565b6001600160a01b03821660009081526003602052604090205460ff166108ff5760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b03821660009081526008602052604090206109218282612b10565b505050565b61092e611c01565b826001600160a01b0316826001600160a01b03160361095f5760405162461bcd60e51b815260040161029090612bd0565b3360008181526010602090815260408083206001600160a01b03888116808652918452828520908816808652935292819020805460ff19168615159081179091559051632ae22fdf60e11b81526004810193909352602483019190915260448201526355c45fbe906064015b600060405180830381600087803b1580156109e557600080fd5b505af11580156109f9573d6000803e3d6000fd5b50505050505050565b610a0a611c01565b610a268484848460405180602001604052806000815250610ffe565b50505050565b610a34611c30565b61092183838360405180602001604052806000815250611514565b6001600160a01b03811660009081526003602052604090205460609060ff168015610a7c575060075460ff165b610ab15760405162461bcd60e51b815260040161029090602080825260049082015263722f637360e01b604082015260600190565b6001600160a01b03821660009081526006602052604090208054610ad490612a96565b80601f0160208091040260200160405190810160405280929190818152602001828054610b0090612a96565b8015610b4d5780601f10610b2257610100808354040283529160200191610b4d565b820191906000526020600020905b815481529060010190602001808311610b3057829003601f168201915b50505050509050919050565b6001600160a01b03821660009081526003602052604081205460ff16610b915760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b038216151580610bda57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614155b610c0f5760405162461bcd60e51b81526020600482015260066024820152651817b13ab93760d11b6044820152606401610290565b6001600160a01b03831660009081526002602052604090205461400090610c3790600e612a66565b6001600160a01b0384166000908152600d6020526040902054610c5b92911c612beb565b90505b92915050565b6001600160a01b03811660009081526003602052604090205460609060ff16610c9f5760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b03821660009081526005602052604090208054610ad490612a96565b610cca611c01565b6000610cd633836116d8565b9050806001600160a01b0316836001600160a01b031603610d1d5760405162461bcd60e51b81526020600482015260016024820152606f60f81b6044820152606401610290565b806001600160a01b0316846001600160a01b03161480610d435750610d43338286611465565b610d5f5760405162461bcd60e51b815260040161029090612bd0565b33600090815260026020526040902054610a26908490610d80856005612a66565b610d8a9190612a29565b83611c6e565b610d98611ba7565b6001600160a01b03821660009081526003602052604090205460ff16610dd05760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b03821660009081526006602052604090206109218282612b10565b610dfa611ba7565b6040516370a0823160e01b81523060048201526001600160a01b0382169063a9059cbb90339083906370a0823190602401602060405180830381865afa158015610e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6c9190612bff565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610eb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edb9190612c18565b5050565b610ee7611c01565b33600090815260026020526040902054610f1b90859085908590610f0c866005612a66565b610f169190612a29565b611cc6565b6040516323de665160e01b815233906323de665190610f4290869086908690600401612c35565b600060405180830381600087803b158015610f5c57600080fd5b505af1158015610f70573d6000803e3d6000fd5b5050505050505050565b6001600160a01b03821660009081526003602052604081205460ff16610fb25760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b038316600090815260026020526040902054610c5b90610fda846005612a66565b610fe49190612a29565b83611f30565b610ff2611ba7565b610ffc6000611f83565b565b611006611c01565b3360009081526002602052604090205461102b90869086908690610f0c876005612a66565b6040516323de665160e01b815233906323de66519061105290879087908790600401612c35565b600060405180830381600087803b15801561106c57600080fd5b505af1158015611080573d6000803e3d6000fd5b505050506110918585858585611fd3565b6110ad5760405162461bcd60e51b815260040161029090612c59565b5050505050565b6001600160a01b03821660009081526003602052604081205460ff166110ec5760405162461bcd60e51b8152600401610290906129dd565b6005600b546110fb9190612a52565b821061112d5760405162461bcd60e51b81526020600482015260016024820152606760f81b6044820152606401610290565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661116184846116d8565b6001600160a01b0316036111875760405162461bcd60e51b8152600401610290906129f8565b50919050565b6001600160a01b03831660009081526003602052604081205460ff166111c55760405162461bcd60e51b8152600401610290906129dd565b6111cf8484610b59565b82106111ed5760405162461bcd60e51b8152600401610290906129f8565b600b546001600160a01b03851660009081526002602052604081205481908190815b61121a600587612a52565b811015610889578161122d826005612a66565b6112379190612a29565b6000818152600c60205260409020549093506001600160a01b0316801561125c578094505b896001600160a01b0316856001600160a01b0316036112985788860361128a575095506112ab945050505050565b8561129481612a7d565b9650505b50806112a381612a7d565b91505061120f565b9392505050565b6005600454106112e95760405162461bcd60e51b815260206004820152600260248201526136b960f11b6044820152606401610290565b6000546001600160a01b031632146113135760405162461bcd60e51b815260040161029090612bd0565b60048054600090815260016020908152604080832080546001600160a01b0319163390811790915593549383526002825280832093909355600590522061135a8582612b10565b503360009081526006602052604090206113748482612b10565b5033600090815260086020526040902061138e8382612b10565b503360009081526009602052604090206113a88282612b10565b50336000908152600360205260408120805460ff1916600117905560048054916113d183612a7d565b919050555050505050565b6113e4611ba7565b6001600160a01b03821660009081526003602052604090205460ff16801561140e575060075460ff165b6114435760405162461bcd60e51b815260040161029090602080825260049082015263722f637360e01b604082015260600190565b6001600160a01b03821660009081526005602052604090206109218282612b10565b6001600160a01b03831660009081526003602052604081205460ff1661149d5760405162461bcd60e51b8152600401610290906129dd565b506001600160a01b0392831660009081526010602090815260408083209486168352938152838220929094168152925290205460ff1690565b6000546001600160a01b031632146115005760405162461bcd60e51b815260040161029090612bd0565b600a80546001600160a01b03191633179055565b61151c611c30565b61152683836120d1565b61154e8460008560016005600b5461153e9190612a52565b6115489190612c74565b85611fd3565b610a265760405162461bcd60e51b815260040161029090612c59565b6001600160a01b03811660009081526003602052604090205460609060ff166115a55760405162461bcd60e51b8152600401610290906129dd565b6115ae82610c64565b6001600160a01b0380841660009081526008602090815260408083206009909252909120600a54919290916115e391166122b3565b6040516020016115f69493929190612d16565b6040516020818303038152906040529050919050565b6001600160a01b03811660009081526003602052604081205460ff166116445760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b0382166000908152600e6020526040902054600b5461166c90600590612a52565b610c5e9190612c74565b61167e611ba7565b6001600160a01b03821660009081526003602052604090205460ff166116b65760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b03821660009081526009602052604090206109218282612b10565b6001600160a01b03821660009081526003602052604081205460ff166117105760405162461bcd60e51b8152600401610290906129dd565b6005600b5461171f9190612a52565b82106117515760405162461bcd60e51b81526020600482015260016024820152601d60fa1b6044820152606401610290565b6001600160a01b0383166000908152600260205260408120549081611777856005612a66565b6117819190612a29565b90505b6000818152600c60205260409020546001600160a01b031680156117ac579250610c5e915050565b50806117b781612e59565b915050611784565b6117c7611ba7565b60075460ff166117fe5760405162461bcd60e51b8152602060048201526002602482015261637360f01b6044820152606401610290565b6007805460ff19169055565b336001600160a01b038316036118325760405162461bcd60e51b815260040161029090612bd0565b60005b60058110156109215760008181526001602052604090819020549051632a265c1f60e21b81526001600160a01b03858116600483015290911690819063a899707c90602401602060405180830381865afa158015611897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bb9190612c18565b156118d85760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b03818116600081815260106020908152604080832033808552908352818420958a168085529590925291829020805460ff19168815159081179091559151632ae22fdf60e11b8152600481019190915260248101939093526044830152906355c45fbe90606401600060405180830381600087803b15801561196057600080fd5b505af1158015611974573d6000803e3d6000fd5b5050505050808061198490612a7d565b915050611835565b6001600160a01b03821660009081526003602052604081205460ff166119c45760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b0383166000908152600260205260408120546119e8846005612a66565b6119f29190612a29565b90506119fe8184611f30565b611a1a5760405162461bcd60e51b815260040161029090612bd0565b6000908152600f60205260409020546001600160a01b03169392505050565b611a41611ba7565b6001600160a01b038116611aa65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610290565b611aaf81611f83565b50565b611aba611c01565b611b0582611ac833846116d8565b336000908152600260205260409020547f000000000000000000000000000000000000000000000000000000000000000090610f0c866005612a66565b336000908152600e60205260408120805460019290611b25908490612a29565b90915550506040516323de665160e01b815233906323de665190611b719085907f0000000000000000000000000000000000000000000000000000000000000000908690600401612c35565b600060405180830381600087803b158015611b8b57600080fd5b505af1158015611b9f573d6000803e3d6000fd5b505050505050565b6000546001600160a01b03163314610ffc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610290565b3360009081526003602052604090205460ff16610ffc5760405162461bcd60e51b8152600401610290906129dd565b600a546001600160a01b03163314610ffc5760405162461bcd60e51b81526020600482015260016024820152606d60f81b6044820152606401610290565b6000828152600f6020526040902080546001600160a01b0319166001600160a01b03851617905533635687f2b88285611ca8600587612a52565b6040518463ffffffff1660e01b81526004016109cb93929190612c35565b6000611cd3600583612a52565b90506000611ce133836116d8565b90506000816001600160a01b0316876001600160a01b03161480611d1f5750866001600160a01b0316611d14338561198c565b6001600160a01b0316145b80611d305750611d30338389611465565b9050808015611d505750856001600160a01b0316826001600160a01b0316145b611d6c5760405162461bcd60e51b815260040161029090612bd0565b856001600160a01b0316826001600160a01b031614611db15760405162461bcd60e51b81526020600482015260016024820152606f60f81b6044820152606401610290565b6001600160a01b038516611deb5760405162461bcd60e51b81526020600482015260016024820152600360fc1b6044820152606401610290565b611df760008584611c6e565b33600090815260026020526040902054611e1290600e612a66565b6001600160a01b0387166000908152600d602052604081208054600190931b92909190611e40908490612c74565b909155505033600090815260026020526040902054611e6090600e612a66565b6001600160a01b0386166000908152600d602052604081208054600190931b92909190611e8e908490612a29565b90915550506000848152600c6020526040812080546001600160a01b0319166001600160a01b038816179055611ec5856001612a29565b6000818152600c60205260409020549091506001600160a01b0316610f7057611ef881611ef3600582612a52565b611f30565b15610f70576000818152600c6020526040902080546001600160a01b0385166001600160a01b03199091161790555050505050505050565b6000600b5483108015610c5b5750506000908152600c60205260409020547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161415919050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006001600160a01b0384163b156120c957604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612017908990899088908890600401612e70565b6020604051808303816000875af1925050508015612052575060408051601f3d908101601f1916820190925261204f91810190612ead565b60015b6120af573d808015612080576040519150601f19603f3d011682016040523d82523d6000602084013e612085565b606091505b5080516000036120a75760405162461bcd60e51b815260040161029090612c59565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506108b6565b5060016108b6565b60006005600b546120e29190612a52565b90506001600160a01b03831661211e5760405162461bcd60e51b81526020600482015260016024820152600360fc1b6044820152606401610290565b61212a600b5482611f30565b156121475760405162461bcd60e51b815260040161029090612bd0565b6000805b60058110156121805761215f81600e612a66565b61216c9085901b83612a29565b91508061217881612a7d565b91505061214b565b506001600160a01b0384166000908152600d60205260409020546121a5908290612a29565b6001600160a01b0385166000818152600d6020908152604080832094909455600b548252600c905291822080546001600160a01b031916909117905582905b8481101561229d5760005b600581101561227c576000818152600160205260408082205490516323de665160e01b81526001600160a01b03909116916323de66519161223791908b908890600401612c35565b600060405180830381600087803b15801561225157600080fd5b505af1158015612265573d6000803e3d6000fd5b50505050808061227490612a7d565b9150506121ef565b508161228781612a7d565b925050808061229590612a7d565b9150506121e4565b506122a9816005612a66565b600b555050505050565b6060610c5e826122c2846122ca565b600101612334565b600080608083901c156122e25760809290921c916010015b604083901c156122f75760409290921c916008015b602083901c1561230c5760209290921c916004015b601083901c156123215760109290921c916002015b600883901c15610c5e5760010192915050565b60606000612343836002612a66565b61234e906002612a29565b67ffffffffffffffff81111561236657612366612539565b6040519080825280601f01601f191660200182016040528015612390576020820181803683370190505b509050600360fc1b816000815181106123ab576123ab612ed7565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106123da576123da612ed7565b60200101906001600160f81b031916908160001a90535060006123fe846002612a66565b612409906001612a29565b90505b6001811115612481576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061243d5761243d612ed7565b1a60f81b82828151811061245357612453612ed7565b60200101906001600160f81b031916908160001a90535060049490941c9361247a81612e59565b905061240c565b508315610c5b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610290565b80356001600160a01b03811681146124e757600080fd5b919050565b600080600080600060a0868803121561250457600080fd5b61250d866124d0565b945061251b602087016124d0565b94979496505050506040830135926060810135926080909101359150565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261256057600080fd5b813567ffffffffffffffff8082111561257b5761257b612539565b604051601f8301601f19908116603f011681019082821181831017156125a3576125a3612539565b816040528381528660208588010111156125bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080604083850312156125ef57600080fd5b6125f8836124d0565b9150602083013567ffffffffffffffff81111561261457600080fd5b6126208582860161254f565b9150509250929050565b8015158114611aaf57600080fd5b60008060006060848603121561264d57600080fd5b612656846124d0565b9250612664602085016124d0565b915060408401356126748161262a565b809150509250925092565b6000806000806080858703121561269557600080fd5b61269e856124d0565b93506126ac602086016124d0565b92506126ba604086016124d0565b9396929550929360600135925050565b6000806000606084860312156126df57600080fd5b6126e8846124d0565b92506126f6602085016124d0565b9150604084013590509250925092565b60006020828403121561271857600080fd5b610c5b826124d0565b60005b8381101561273c578181015183820152602001612724565b50506000910152565b6000815180845261275d816020860160208601612721565b601f01601f19169290920160200192915050565b602081526000610c5b6020830184612745565b6000806040838503121561279757600080fd5b6127a0836124d0565b91506127ae602084016124d0565b90509250929050565b600080604083850312156127ca57600080fd5b6127d3836124d0565b946020939093013593505050565b600080600080600060a086880312156127f957600080fd5b612802866124d0565b9450612810602087016124d0565b935061281e604087016124d0565b925060608601359150608086013567ffffffffffffffff81111561284157600080fd5b61284d8882890161254f565b9150509295509295909350565b6000806000806080858703121561287057600080fd5b843567ffffffffffffffff8082111561288857600080fd5b6128948883890161254f565b955060208701359150808211156128aa57600080fd5b6128b68883890161254f565b945060408701359150808211156128cc57600080fd5b6128d88883890161254f565b935060608701359150808211156128ee57600080fd5b506128fb8782880161254f565b91505092959194509250565b60008060006060848603121561291c57600080fd5b612925846124d0565b9250612933602085016124d0565b9150612941604085016124d0565b90509250925092565b6000806000806080858703121561296057600080fd5b612969856124d0565b9350612977602086016124d0565b925060408501359150606085013567ffffffffffffffff81111561299a57600080fd5b6128fb8782880161254f565b600080604083850312156129b957600080fd5b6129c2836124d0565b915060208301356129d28161262a565b809150509250929050565b6020808252600190820152603960f91b604082015260600190565b6020808252600190820152603160f91b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b80820180821115610c5e57610c5e612a13565b634e487b7160e01b600052601260045260246000fd5b600082612a6157612a61612a3c565b500490565b8082028115828204841417610c5e57610c5e612a13565b600060018201612a8f57612a8f612a13565b5060010190565b600181811c90821680612aaa57607f821691505b60208210810361118757634e487b7160e01b600052602260045260246000fd5b601f82111561092157600081815260208120601f850160051c81016020861015612af15750805b601f850160051c820191505b81811015611b9f57828155600101612afd565b815167ffffffffffffffff811115612b2a57612b2a612539565b612b3e81612b388454612a96565b84612aca565b602080601f831160018114612b735760008415612b5b5750858301515b600019600386901b1c1916600185901b178555611b9f565b600085815260208120601f198616915b82811015612ba257888601518255948401946001909101908401612b83565b5085821015612bc05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6020808252600190820152606160f81b604082015260600190565b600082612bfa57612bfa612a3c565b500690565b600060208284031215612c1157600080fd5b5051919050565b600060208284031215612c2a57600080fd5b8151610c5b8161262a565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6020808252600190820152603d60f91b604082015260600190565b81810381811115610c5e57610c5e612a13565b60008151612c99818560208601612721565b9290920192915050565b60008154612cb081612a96565b60018281168015612cc85760018114612cdd57612d0c565b60ff1984168752821515830287019450612d0c565b8560005260208060002060005b85811015612d035781548a820152908401908201612cea565b50505082870194505b5050505092915050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b757466382c7b226e616d81526332911d1160e11b602082015260008551612d5b816024850160208a01612721565b61088b60f21b60249184019182018190526e113232b9b1b934b83a34b7b7111d1160891b6026830152612d916035830188612ca3565b818152681134b6b0b3b2911d1160b91b60028201529150612db5600b830187612ca3565b9081527f2265787465726e616c5f6c696e6b223a2268747470733a2f2f6372756465626f6002820152681c9b994b9ddd19888b60ba1b60228201527f2273656c6c65725f6665655f62617369735f706f696e7473223a3530302c2266602b8201526e32b2afb932b1b4b834b2b73a111d1160891b604b8201529050612e4e612e40605a830186612c87565b61227d60f01b815260020190565b979650505050505050565b600081612e6857612e68612a13565b506000190190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612ea390830184612745565b9695505050505050565b600060208284031215612ebf57600080fd5b81516001600160e01b031981168114610c5b57600080fd5b634e487b7160e01b600052603260045260246000fdfea26469706673582212207d8bb40f9095592d2bda4a1cb89b4ef99cc4aadfafd3fa45c4cadfc6aba6bea964736f6c63430008110033
Deployed Bytecode
0x6080604052600436106102085760003560e01c80638da5cb5b11610118578063bac5ccc3116100a0578063e03313741161006f578063e03313741461069e578063e3712368146106b3578063e4999080146106d3578063f2fde38b146106f3578063fea6eb9e1461071357600080fd5b8063bac5ccc31461061e578063c240d9201461063e578063cfcc7e7a1461065e578063d2f6f67d1461067e57600080fd5b8063a6015db4116100e7578063a6015db414610589578063a9d2f455146105a9578063acb608b3146105c9578063b2238c9d146105de578063b4069dc8146105fe57600080fd5b80638da5cb5b1461050b57806391bd54f514610529578063962bf1f914610549578063a1601ad31461056957600080fd5b80632d53a1221161019b578063622574671161016a578063622574671461044a5780636bcfc62a1461046a57806370d5ae051461048a578063715018a6146104d65780637d706301146104eb57600080fd5b80632d53a122146103c0578063356bfa88146103e05780633dba0ac41461040057806349df728c1461042a57600080fd5b80631bd92142116101d75780631bd92142146103335780631ce102c614610353578063204d849a1461038057806321b24583146103a057600080fd5b806301b03a72146102a05780630d060ae0146102d35780631168132c146102f357806312f20cb51461031357600080fd5b3661029b57600a546040516000916001600160a01b03169034908381818185875af1925050503d806000811461025a576040519150601f19603f3d011682016040523d82523d6000602084013e61025f565b606091505b50509050806102995760405162461bcd60e51b81526020600482015260016024820152602360f91b60448201526064015b60405180910390fd5b005b600080fd5b3480156102ac57600080fd5b506102c06102bb3660046124ec565b610733565b6040519081526020015b60405180910390f35b3480156102df57600080fd5b506102996102ee3660046125dc565b6108bf565b3480156102ff57600080fd5b5061029961030e366004612638565b610926565b34801561031f57600080fd5b5061029961032e36600461267f565b610a02565b34801561033f57600080fd5b5061029961034e3660046126ca565b610a2c565b34801561035f57600080fd5b5061037361036e366004612706565b610a4f565b6040516102ca9190612771565b34801561038c57600080fd5b506102c061039b366004612784565b610b59565b3480156103ac57600080fd5b506103736103bb366004612706565b610c64565b3480156103cc57600080fd5b506102996103db3660046126ca565b610cc2565b3480156103ec57600080fd5b506102996103fb3660046125dc565b610d90565b34801561040c57600080fd5b5060075461041a9060ff1681565b60405190151581526020016102ca565b34801561043657600080fd5b50610299610445366004612706565b610df2565b34801561045657600080fd5b5061029961046536600461267f565b610edf565b34801561047657600080fd5b5061041a6104853660046127b7565b610f7a565b34801561049657600080fd5b506104be7f000000000000000000000000000000000000000000000000000000000000dead81565b6040516001600160a01b0390911681526020016102ca565b3480156104e257600080fd5b50610299610fea565b3480156104f757600080fd5b506102996105063660046127e1565b610ffe565b34801561051757600080fd5b506000546001600160a01b03166104be565b34801561053557600080fd5b506102c06105443660046127b7565b6110b4565b34801561055557600080fd5b506102c06105643660046126ca565b61118d565b34801561057557600080fd5b5061029961058436600461285a565b6112b2565b34801561059557600080fd5b506102996105a43660046125dc565b6113dc565b3480156105b557600080fd5b5061041a6105c4366004612907565b611465565b3480156105d557600080fd5b506102996114d6565b3480156105ea57600080fd5b506102996105f936600461294a565b611514565b34801561060a57600080fd5b50610373610619366004612706565b61156a565b34801561062a57600080fd5b506102c0610639366004612706565b61160c565b34801561064a57600080fd5b506102996106593660046125dc565b611676565b34801561066a57600080fd5b506104be6106793660046127b7565b6116d8565b34801561068a57600080fd5b50600a546104be906001600160a01b031681565b3480156106aa57600080fd5b506102996117bf565b3480156106bf57600080fd5b506102996106ce3660046129a6565b61180a565b3480156106df57600080fd5b506104be6106ee3660046127b7565b61198c565b3480156106ff57600080fd5b5061029961070e366004612706565b611a39565b34801561071f57600080fd5b5061029961072e3660046127b7565b611ab2565b6001600160a01b03851660009081526003602052604081205460ff1661076b5760405162461bcd60e51b8152600401610290906129dd565b6107758686610b59565b84106107935760405162461bcd60e51b8152600401610290906129f8565b600b54600083156107ae576107a9846001612a29565b6107b1565b60005b6001600160a01b0389166000908152600260205260408120549192509081908188156107e7576107e2896001612a29565b6107ea565b60005b90505b6107f8600587612a52565b811015610889578161080b826005612a66565b6108159190612a29565b6000818152600c60205260409020549093506001600160a01b0316801561083a578094505b8b6001600160a01b0316856001600160a01b031603610876578a8603610868575095506108b6945050505050565b8561087281612a7d565b9650505b508061088181612a7d565b9150506107ed565b5060405162461bcd60e51b81526020600482015260016024820152607560f81b6044820152606401610290565b95945050505050565b6108c7611ba7565b6001600160a01b03821660009081526003602052604090205460ff166108ff5760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b03821660009081526008602052604090206109218282612b10565b505050565b61092e611c01565b826001600160a01b0316826001600160a01b03160361095f5760405162461bcd60e51b815260040161029090612bd0565b3360008181526010602090815260408083206001600160a01b03888116808652918452828520908816808652935292819020805460ff19168615159081179091559051632ae22fdf60e11b81526004810193909352602483019190915260448201526355c45fbe906064015b600060405180830381600087803b1580156109e557600080fd5b505af11580156109f9573d6000803e3d6000fd5b50505050505050565b610a0a611c01565b610a268484848460405180602001604052806000815250610ffe565b50505050565b610a34611c30565b61092183838360405180602001604052806000815250611514565b6001600160a01b03811660009081526003602052604090205460609060ff168015610a7c575060075460ff165b610ab15760405162461bcd60e51b815260040161029090602080825260049082015263722f637360e01b604082015260600190565b6001600160a01b03821660009081526006602052604090208054610ad490612a96565b80601f0160208091040260200160405190810160405280929190818152602001828054610b0090612a96565b8015610b4d5780601f10610b2257610100808354040283529160200191610b4d565b820191906000526020600020905b815481529060010190602001808311610b3057829003601f168201915b50505050509050919050565b6001600160a01b03821660009081526003602052604081205460ff16610b915760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b038216151580610bda57507f000000000000000000000000000000000000000000000000000000000000dead6001600160a01b0316826001600160a01b031614155b610c0f5760405162461bcd60e51b81526020600482015260066024820152651817b13ab93760d11b6044820152606401610290565b6001600160a01b03831660009081526002602052604090205461400090610c3790600e612a66565b6001600160a01b0384166000908152600d6020526040902054610c5b92911c612beb565b90505b92915050565b6001600160a01b03811660009081526003602052604090205460609060ff16610c9f5760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b03821660009081526005602052604090208054610ad490612a96565b610cca611c01565b6000610cd633836116d8565b9050806001600160a01b0316836001600160a01b031603610d1d5760405162461bcd60e51b81526020600482015260016024820152606f60f81b6044820152606401610290565b806001600160a01b0316846001600160a01b03161480610d435750610d43338286611465565b610d5f5760405162461bcd60e51b815260040161029090612bd0565b33600090815260026020526040902054610a26908490610d80856005612a66565b610d8a9190612a29565b83611c6e565b610d98611ba7565b6001600160a01b03821660009081526003602052604090205460ff16610dd05760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b03821660009081526006602052604090206109218282612b10565b610dfa611ba7565b6040516370a0823160e01b81523060048201526001600160a01b0382169063a9059cbb90339083906370a0823190602401602060405180830381865afa158015610e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6c9190612bff565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610eb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edb9190612c18565b5050565b610ee7611c01565b33600090815260026020526040902054610f1b90859085908590610f0c866005612a66565b610f169190612a29565b611cc6565b6040516323de665160e01b815233906323de665190610f4290869086908690600401612c35565b600060405180830381600087803b158015610f5c57600080fd5b505af1158015610f70573d6000803e3d6000fd5b5050505050505050565b6001600160a01b03821660009081526003602052604081205460ff16610fb25760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b038316600090815260026020526040902054610c5b90610fda846005612a66565b610fe49190612a29565b83611f30565b610ff2611ba7565b610ffc6000611f83565b565b611006611c01565b3360009081526002602052604090205461102b90869086908690610f0c876005612a66565b6040516323de665160e01b815233906323de66519061105290879087908790600401612c35565b600060405180830381600087803b15801561106c57600080fd5b505af1158015611080573d6000803e3d6000fd5b505050506110918585858585611fd3565b6110ad5760405162461bcd60e51b815260040161029090612c59565b5050505050565b6001600160a01b03821660009081526003602052604081205460ff166110ec5760405162461bcd60e51b8152600401610290906129dd565b6005600b546110fb9190612a52565b821061112d5760405162461bcd60e51b81526020600482015260016024820152606760f81b6044820152606401610290565b7f000000000000000000000000000000000000000000000000000000000000dead6001600160a01b031661116184846116d8565b6001600160a01b0316036111875760405162461bcd60e51b8152600401610290906129f8565b50919050565b6001600160a01b03831660009081526003602052604081205460ff166111c55760405162461bcd60e51b8152600401610290906129dd565b6111cf8484610b59565b82106111ed5760405162461bcd60e51b8152600401610290906129f8565b600b546001600160a01b03851660009081526002602052604081205481908190815b61121a600587612a52565b811015610889578161122d826005612a66565b6112379190612a29565b6000818152600c60205260409020549093506001600160a01b0316801561125c578094505b896001600160a01b0316856001600160a01b0316036112985788860361128a575095506112ab945050505050565b8561129481612a7d565b9650505b50806112a381612a7d565b91505061120f565b9392505050565b6005600454106112e95760405162461bcd60e51b815260206004820152600260248201526136b960f11b6044820152606401610290565b6000546001600160a01b031632146113135760405162461bcd60e51b815260040161029090612bd0565b60048054600090815260016020908152604080832080546001600160a01b0319163390811790915593549383526002825280832093909355600590522061135a8582612b10565b503360009081526006602052604090206113748482612b10565b5033600090815260086020526040902061138e8382612b10565b503360009081526009602052604090206113a88282612b10565b50336000908152600360205260408120805460ff1916600117905560048054916113d183612a7d565b919050555050505050565b6113e4611ba7565b6001600160a01b03821660009081526003602052604090205460ff16801561140e575060075460ff165b6114435760405162461bcd60e51b815260040161029090602080825260049082015263722f637360e01b604082015260600190565b6001600160a01b03821660009081526005602052604090206109218282612b10565b6001600160a01b03831660009081526003602052604081205460ff1661149d5760405162461bcd60e51b8152600401610290906129dd565b506001600160a01b0392831660009081526010602090815260408083209486168352938152838220929094168152925290205460ff1690565b6000546001600160a01b031632146115005760405162461bcd60e51b815260040161029090612bd0565b600a80546001600160a01b03191633179055565b61151c611c30565b61152683836120d1565b61154e8460008560016005600b5461153e9190612a52565b6115489190612c74565b85611fd3565b610a265760405162461bcd60e51b815260040161029090612c59565b6001600160a01b03811660009081526003602052604090205460609060ff166115a55760405162461bcd60e51b8152600401610290906129dd565b6115ae82610c64565b6001600160a01b0380841660009081526008602090815260408083206009909252909120600a54919290916115e391166122b3565b6040516020016115f69493929190612d16565b6040516020818303038152906040529050919050565b6001600160a01b03811660009081526003602052604081205460ff166116445760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b0382166000908152600e6020526040902054600b5461166c90600590612a52565b610c5e9190612c74565b61167e611ba7565b6001600160a01b03821660009081526003602052604090205460ff166116b65760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b03821660009081526009602052604090206109218282612b10565b6001600160a01b03821660009081526003602052604081205460ff166117105760405162461bcd60e51b8152600401610290906129dd565b6005600b5461171f9190612a52565b82106117515760405162461bcd60e51b81526020600482015260016024820152601d60fa1b6044820152606401610290565b6001600160a01b0383166000908152600260205260408120549081611777856005612a66565b6117819190612a29565b90505b6000818152600c60205260409020546001600160a01b031680156117ac579250610c5e915050565b50806117b781612e59565b915050611784565b6117c7611ba7565b60075460ff166117fe5760405162461bcd60e51b8152602060048201526002602482015261637360f01b6044820152606401610290565b6007805460ff19169055565b336001600160a01b038316036118325760405162461bcd60e51b815260040161029090612bd0565b60005b60058110156109215760008181526001602052604090819020549051632a265c1f60e21b81526001600160a01b03858116600483015290911690819063a899707c90602401602060405180830381865afa158015611897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bb9190612c18565b156118d85760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b03818116600081815260106020908152604080832033808552908352818420958a168085529590925291829020805460ff19168815159081179091559151632ae22fdf60e11b8152600481019190915260248101939093526044830152906355c45fbe90606401600060405180830381600087803b15801561196057600080fd5b505af1158015611974573d6000803e3d6000fd5b5050505050808061198490612a7d565b915050611835565b6001600160a01b03821660009081526003602052604081205460ff166119c45760405162461bcd60e51b8152600401610290906129dd565b6001600160a01b0383166000908152600260205260408120546119e8846005612a66565b6119f29190612a29565b90506119fe8184611f30565b611a1a5760405162461bcd60e51b815260040161029090612bd0565b6000908152600f60205260409020546001600160a01b03169392505050565b611a41611ba7565b6001600160a01b038116611aa65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610290565b611aaf81611f83565b50565b611aba611c01565b611b0582611ac833846116d8565b336000908152600260205260409020547f000000000000000000000000000000000000000000000000000000000000dead90610f0c866005612a66565b336000908152600e60205260408120805460019290611b25908490612a29565b90915550506040516323de665160e01b815233906323de665190611b719085907f000000000000000000000000000000000000000000000000000000000000dead908690600401612c35565b600060405180830381600087803b158015611b8b57600080fd5b505af1158015611b9f573d6000803e3d6000fd5b505050505050565b6000546001600160a01b03163314610ffc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610290565b3360009081526003602052604090205460ff16610ffc5760405162461bcd60e51b8152600401610290906129dd565b600a546001600160a01b03163314610ffc5760405162461bcd60e51b81526020600482015260016024820152606d60f81b6044820152606401610290565b6000828152600f6020526040902080546001600160a01b0319166001600160a01b03851617905533635687f2b88285611ca8600587612a52565b6040518463ffffffff1660e01b81526004016109cb93929190612c35565b6000611cd3600583612a52565b90506000611ce133836116d8565b90506000816001600160a01b0316876001600160a01b03161480611d1f5750866001600160a01b0316611d14338561198c565b6001600160a01b0316145b80611d305750611d30338389611465565b9050808015611d505750856001600160a01b0316826001600160a01b0316145b611d6c5760405162461bcd60e51b815260040161029090612bd0565b856001600160a01b0316826001600160a01b031614611db15760405162461bcd60e51b81526020600482015260016024820152606f60f81b6044820152606401610290565b6001600160a01b038516611deb5760405162461bcd60e51b81526020600482015260016024820152600360fc1b6044820152606401610290565b611df760008584611c6e565b33600090815260026020526040902054611e1290600e612a66565b6001600160a01b0387166000908152600d602052604081208054600190931b92909190611e40908490612c74565b909155505033600090815260026020526040902054611e6090600e612a66565b6001600160a01b0386166000908152600d602052604081208054600190931b92909190611e8e908490612a29565b90915550506000848152600c6020526040812080546001600160a01b0319166001600160a01b038816179055611ec5856001612a29565b6000818152600c60205260409020549091506001600160a01b0316610f7057611ef881611ef3600582612a52565b611f30565b15610f70576000818152600c6020526040902080546001600160a01b0385166001600160a01b03199091161790555050505050505050565b6000600b5483108015610c5b5750506000908152600c60205260409020547f000000000000000000000000000000000000000000000000000000000000dead6001600160a01b0390811691161415919050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006001600160a01b0384163b156120c957604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612017908990899088908890600401612e70565b6020604051808303816000875af1925050508015612052575060408051601f3d908101601f1916820190925261204f91810190612ead565b60015b6120af573d808015612080576040519150601f19603f3d011682016040523d82523d6000602084013e612085565b606091505b5080516000036120a75760405162461bcd60e51b815260040161029090612c59565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506108b6565b5060016108b6565b60006005600b546120e29190612a52565b90506001600160a01b03831661211e5760405162461bcd60e51b81526020600482015260016024820152600360fc1b6044820152606401610290565b61212a600b5482611f30565b156121475760405162461bcd60e51b815260040161029090612bd0565b6000805b60058110156121805761215f81600e612a66565b61216c9085901b83612a29565b91508061217881612a7d565b91505061214b565b506001600160a01b0384166000908152600d60205260409020546121a5908290612a29565b6001600160a01b0385166000818152600d6020908152604080832094909455600b548252600c905291822080546001600160a01b031916909117905582905b8481101561229d5760005b600581101561227c576000818152600160205260408082205490516323de665160e01b81526001600160a01b03909116916323de66519161223791908b908890600401612c35565b600060405180830381600087803b15801561225157600080fd5b505af1158015612265573d6000803e3d6000fd5b50505050808061227490612a7d565b9150506121ef565b508161228781612a7d565b925050808061229590612a7d565b9150506121e4565b506122a9816005612a66565b600b555050505050565b6060610c5e826122c2846122ca565b600101612334565b600080608083901c156122e25760809290921c916010015b604083901c156122f75760409290921c916008015b602083901c1561230c5760209290921c916004015b601083901c156123215760109290921c916002015b600883901c15610c5e5760010192915050565b60606000612343836002612a66565b61234e906002612a29565b67ffffffffffffffff81111561236657612366612539565b6040519080825280601f01601f191660200182016040528015612390576020820181803683370190505b509050600360fc1b816000815181106123ab576123ab612ed7565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106123da576123da612ed7565b60200101906001600160f81b031916908160001a90535060006123fe846002612a66565b612409906001612a29565b90505b6001811115612481576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061243d5761243d612ed7565b1a60f81b82828151811061245357612453612ed7565b60200101906001600160f81b031916908160001a90535060049490941c9361247a81612e59565b905061240c565b508315610c5b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610290565b80356001600160a01b03811681146124e757600080fd5b919050565b600080600080600060a0868803121561250457600080fd5b61250d866124d0565b945061251b602087016124d0565b94979496505050506040830135926060810135926080909101359150565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261256057600080fd5b813567ffffffffffffffff8082111561257b5761257b612539565b604051601f8301601f19908116603f011681019082821181831017156125a3576125a3612539565b816040528381528660208588010111156125bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080604083850312156125ef57600080fd5b6125f8836124d0565b9150602083013567ffffffffffffffff81111561261457600080fd5b6126208582860161254f565b9150509250929050565b8015158114611aaf57600080fd5b60008060006060848603121561264d57600080fd5b612656846124d0565b9250612664602085016124d0565b915060408401356126748161262a565b809150509250925092565b6000806000806080858703121561269557600080fd5b61269e856124d0565b93506126ac602086016124d0565b92506126ba604086016124d0565b9396929550929360600135925050565b6000806000606084860312156126df57600080fd5b6126e8846124d0565b92506126f6602085016124d0565b9150604084013590509250925092565b60006020828403121561271857600080fd5b610c5b826124d0565b60005b8381101561273c578181015183820152602001612724565b50506000910152565b6000815180845261275d816020860160208601612721565b601f01601f19169290920160200192915050565b602081526000610c5b6020830184612745565b6000806040838503121561279757600080fd5b6127a0836124d0565b91506127ae602084016124d0565b90509250929050565b600080604083850312156127ca57600080fd5b6127d3836124d0565b946020939093013593505050565b600080600080600060a086880312156127f957600080fd5b612802866124d0565b9450612810602087016124d0565b935061281e604087016124d0565b925060608601359150608086013567ffffffffffffffff81111561284157600080fd5b61284d8882890161254f565b9150509295509295909350565b6000806000806080858703121561287057600080fd5b843567ffffffffffffffff8082111561288857600080fd5b6128948883890161254f565b955060208701359150808211156128aa57600080fd5b6128b68883890161254f565b945060408701359150808211156128cc57600080fd5b6128d88883890161254f565b935060608701359150808211156128ee57600080fd5b506128fb8782880161254f565b91505092959194509250565b60008060006060848603121561291c57600080fd5b612925846124d0565b9250612933602085016124d0565b9150612941604085016124d0565b90509250925092565b6000806000806080858703121561296057600080fd5b612969856124d0565b9350612977602086016124d0565b925060408501359150606085013567ffffffffffffffff81111561299a57600080fd5b6128fb8782880161254f565b600080604083850312156129b957600080fd5b6129c2836124d0565b915060208301356129d28161262a565b809150509250929050565b6020808252600190820152603960f91b604082015260600190565b6020808252600190820152603160f91b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b80820180821115610c5e57610c5e612a13565b634e487b7160e01b600052601260045260246000fd5b600082612a6157612a61612a3c565b500490565b8082028115828204841417610c5e57610c5e612a13565b600060018201612a8f57612a8f612a13565b5060010190565b600181811c90821680612aaa57607f821691505b60208210810361118757634e487b7160e01b600052602260045260246000fd5b601f82111561092157600081815260208120601f850160051c81016020861015612af15750805b601f850160051c820191505b81811015611b9f57828155600101612afd565b815167ffffffffffffffff811115612b2a57612b2a612539565b612b3e81612b388454612a96565b84612aca565b602080601f831160018114612b735760008415612b5b5750858301515b600019600386901b1c1916600185901b178555611b9f565b600085815260208120601f198616915b82811015612ba257888601518255948401946001909101908401612b83565b5085821015612bc05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6020808252600190820152606160f81b604082015260600190565b600082612bfa57612bfa612a3c565b500690565b600060208284031215612c1157600080fd5b5051919050565b600060208284031215612c2a57600080fd5b8151610c5b8161262a565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6020808252600190820152603d60f91b604082015260600190565b81810381811115610c5e57610c5e612a13565b60008151612c99818560208601612721565b9290920192915050565b60008154612cb081612a96565b60018281168015612cc85760018114612cdd57612d0c565b60ff1984168752821515830287019450612d0c565b8560005260208060002060005b85811015612d035781548a820152908401908201612cea565b50505082870194505b5050505092915050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b757466382c7b226e616d81526332911d1160e11b602082015260008551612d5b816024850160208a01612721565b61088b60f21b60249184019182018190526e113232b9b1b934b83a34b7b7111d1160891b6026830152612d916035830188612ca3565b818152681134b6b0b3b2911d1160b91b60028201529150612db5600b830187612ca3565b9081527f2265787465726e616c5f6c696e6b223a2268747470733a2f2f6372756465626f6002820152681c9b994b9ddd19888b60ba1b60228201527f2273656c6c65725f6665655f62617369735f706f696e7473223a3530302c2266602b8201526e32b2afb932b1b4b834b2b73a111d1160891b604b8201529050612e4e612e40605a830186612c87565b61227d60f01b815260020190565b979650505050505050565b600081612e6857612e68612a13565b506000190190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612ea390830184612745565b9695505050505050565b600060208284031215612ebf57600080fd5b81516001600160e01b031981168114610c5b57600080fd5b634e487b7160e01b600052603260045260246000fdfea26469706673582212207d8bb40f9095592d2bda4a1cb89b4ef99cc4aadfafd3fa45c4cadfc6aba6bea964736f6c63430008110033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.