Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
EightNapOnChainProjectV1
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 125 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT /* _____/\\\\\\\\\_____/\\\\\_____/\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\___ ___/\\\///////\\\__\/\\\\\\___\/\\\___/\\\\\\\\\\\\\__\/\\\/////////\\\_ __\/\\\_____\/\\\__\/\\\/\\\__\/\\\__/\\\/////////\\\_\/\\\_______\/\\\_ __\///\\\\\\\\\/___\/\\\//\\\_\/\\\_\/\\\_______\/\\\_\/\\\\\\\\\\\\\/__ ___/\\\///////\\\__\/\\\\//\\\\/\\\_\/\\\\\\\\\\\\\\\_\/\\\/////////____ __/\\\______\//\\\_\/\\\_\//\\\/\\\_\/\\\/////////\\\_\/\\\_____________ _\//\\\______/\\\__\/\\\__\//\\\\\\_\/\\\_______\/\\\_\/\\\_____________ __\///\\\\\\\\\/___\/\\\___\//\\\\\_\/\\\_______\/\\\_\/\\\_____________ ____\/////////_____\///_____\/////__\///________\///__\///______________ Smartcontract developed by 8NAPART. */ pragma solidity ^0.8.19; import "./helpers/SSTORE2.sol"; import "./helpers/OwnableUpgradeable.sol"; import "./helpers/ERC721EnumerableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/Base64Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol"; import "./helpers/File.sol"; contract EightNapOnChainProjectV1 is ERC721EnumerableUpgradeable, OwnableUpgradeable { mapping(address => bool) private _addressToClaimed; mapping(uint256 => bytes32) public tokenIdToHash; mapping(uint256 => address) public tokenIdToRevealer; uint256 private _mintPassFlags; //32 uint256 private _withdrawable; // 32 uint56 currentBidEndTimeStamp; // 8 uint56 currentBidStartTimeStamp; // 8 event BaseURISet(string newBaseURI); event MaxSupplySet(uint24 newMaxSupply); event ArtScriptsSet(); event LibraryScriptsSet(); event PieceRevealed(); event NewBidPlaced(Bid bid); struct Project { string name; //unknown string baseURI; //unkown address[] artScripts; //unknown bytes32 merkleRoot; //32 address artInfo; //20 uint56 biddingStartTimeStamp; //8 uint32 maxSupply; //4 address payable twoFiveSix; //20 uint96 mintPassHolderPrice; //12 address payable royaltyAddress; //20 uint96 minBid; //12 address payable artistAddress; //20 uint24 revealerDiscount; //3 uint24 royalty; //3 uint24 eightNapShare; //3 uint24 twoFiveSixShare; //3 address payable eightNap; //20 uint56 mintPassStartTimeStamp; //8 uint32 auctionDuration; //4 address libraryScripts; //20 uint56 allowListStartTimeStamp; //8 uint32 auctionExtension; //4 address mintPassAddress; // 20 uint56 publicStartTimeStamp; //8 uint32 auctionExtenderTimeFrame; // 4 uint96 allowListPrice; //12 uint96 publicPrice; //12 uint32 supplyLeftForAuction; // 4 } struct LibraryScript { address fileStore; string fileName; } struct Bid { address payable bidder; uint256 amount; } struct Auction { Bid highestBid; uint256 tokenId; uint56 endTime; bool claimed; } Project private project; Auction private auction; /** * @notice Initializes the project. * @dev Initializes the ERC721 contract. * @param _p The project data. */ function initProject( Project calldata _p, address _libraryScripts ) public initializer { __ERC721_init(_p.name, "8NAPART"); __Ownable_init(_p.artistAddress); project = _p; if (_libraryScripts != address(0)) { project.libraryScripts = _libraryScripts; } } /** * @notice Mint tokens to an address (artist only) * @dev Mints a given number of tokens to a specified address. Can only be called by the project owner. * @param count The number of tokens to be minted. * @param a The address to which the tokens will be minted. */ function artistMint(uint24 count, address a) public onlyOwner { uint256 totalSupply = _owners.length; require(totalSupply + count < project.maxSupply, "Minted out"); require(count < 5, "Mint max four per tx"); for (uint256 i; i < count; ) { unchecked { uint256 tokenId = totalSupply + i; tokenIdToHash[tokenId] = createHash( tokenId, project.artistAddress ); _mint(a, tokenId); i++; } } } /** * @notice Mint a token to an allow listed address if conditions met. * @dev Mints a token to a specified address if that address is on the project's allow list and has not already claimed a token. * @param proof The proof of inclusion in the project's Merkle tree. * @param a The address to which the token will be minted. */ function allowListMint(bytes32[] memory proof, address a) public payable { require( block.timestamp > project.allowListStartTimeStamp, "Allow list mint not started" ); require( block.timestamp < project.biddingStartTimeStamp || block.timestamp < project.publicStartTimeStamp, "Allow list mint ended" ); require( MerkleProofUpgradeable.verify( proof, project.merkleRoot, keccak256(abi.encodePacked(a)) ), "Not on allow list" ); require(_addressToClaimed[a] == false, "Already claimed"); uint256 totalSupply = _owners.length; if (project.publicStartTimeStamp != 0) { require( totalSupply + 1 < (project.maxSupply - project.supplyLeftForAuction), "Not available" ); } require(totalSupply + 1 < project.maxSupply, "Minted out"); require(project.allowListPrice <= msg.value, "Invalid funds provided"); require(msg.sender == tx.origin, "No contract minting"); unchecked { uint256 tokenId = totalSupply; _addressToClaimed[a] = true; _withdrawable += msg.value; tokenIdToHash[tokenId] = createHash(tokenId, msg.sender); _mint(a, tokenId); } } /** * @notice Allows users to mint tokens using their mint passes. * @dev Users can mint up to four tokens per transaction during the mint pass phase. * @param mintPassIds An array of mint pass IDs the user wants to use for minting. */ function mintPassMint(uint256[] calldata mintPassIds) public payable { require( block.timestamp > project.mintPassStartTimeStamp, "Mint pass mint not started" ); require( block.timestamp < project.allowListStartTimeStamp, "Mint pass mint ended" ); uint256 totalSupply = _owners.length; uint256 count = mintPassIds.length; uint256 total = count * project.mintPassHolderPrice; require(totalSupply + count < project.maxSupply, "Minted out"); require(count > 0, "Mint at least one"); require(count < 5, "Mint max four per tx"); require(total <= msg.value, "Invalid funds provided"); require(msg.sender == tx.origin, "No contract minting"); IERC721Upgradeable mintPassContract = IERC721Upgradeable( project.mintPassAddress ); unchecked { _withdrawable += msg.value; } for (uint256 i; i < count; i++) { address a = mintPassContract.ownerOf(mintPassIds[i]); uint256 tokenId = totalSupply + i; bool isUsed = getMintPassMinted(mintPassIds[i]); require(!isUsed, "Mint pass already used"); _setMintPassUsed(mintPassIds[i]); bytes32 hashOne = createHash(tokenId, msg.sender); tokenIdToHash[tokenId] = hashOne; _mint(a, tokenId); } } /** * @notice Mint a token if conditions met. * @dev Mints a token to a specified address. * @param a The address to which the token will be minted. */ function publicMint(address a, uint256 count) public payable { require(project.publicStartTimeStamp != 0, "No public mint"); require( block.timestamp > project.publicStartTimeStamp, "Public mint not started" ); uint256 total = count * project.publicPrice; uint256 totalSupply = _owners.length; require( totalSupply + count < (project.maxSupply - project.supplyLeftForAuction), "Not available" ); require(count > 0, "Mint at least one"); require(count < 5, "Mint max four per tx"); require(total <= msg.value, "Invalid funds provided"); require(msg.sender == tx.origin, "No contract minting"); unchecked { _withdrawable += msg.value; } for (uint256 i; i < count; i++) { uint256 tokenId = totalSupply + i; tokenIdToHash[tokenId] = createHash(tokenId, msg.sender); _mint(a, tokenId); } } /** * @notice Checks if a given mint pass has already been used. * @param mintPassId The ID of the mint pass to check. * @return bool Whether the mint pass has been used. */ function getMintPassMinted(uint256 mintPassId) public view returns (bool) { uint256 mask = (1 << mintPassId); return (_mintPassFlags & mask) != 0; } /** * @dev Marks a given mint pass as used. * @param _mintPassId The ID of the mint pass to mark as used. */ function _setMintPassUsed(uint256 _mintPassId) private { uint256 mask = (1 << _mintPassId); _mintPassFlags = _mintPassFlags | mask; } /** * @notice Reveals the next piece to be auctioned. * @dev Resets the auction state and sets up the next token for auction. */ function revealNextPiece() public { if (project.publicStartTimeStamp != 0) { require( block.timestamp > project.publicStartTimeStamp && (_owners.length + 1 >= project.maxSupply - project.supplyLeftForAuction), "Bidding phase not started" ); } else { require( block.timestamp > project.biddingStartTimeStamp, "Bidding phase not started" ); } require(msg.sender == tx.origin, "No contract revealing"); require(block.timestamp > auction.endTime, "Auction in progress"); if (!auction.claimed && auction.highestBid.amount > 0) { _claim(); } require(_owners.length + 1 < project.maxSupply, "Minted out"); require(auction.tokenId == 0, "Already revealed"); uint256 nextTokenId = _owners.length; tokenIdToHash[nextTokenId] = createHash(nextTokenId, msg.sender); tokenIdToRevealer[nextTokenId] = msg.sender; delete auction.claimed; delete auction.endTime; delete auction.highestBid; auction.tokenId = nextTokenId; emit PieceRevealed(); } /** * @notice Allows users to place a bid on the current auction. * @dev Users can outbid the current highest bid by at least 5%. */ function placeBid() public payable { require( tokenIdToHash[_owners.length] != bytes32(0), "Reveal piece first" ); require(msg.value >= project.minBid, "Bid is lower than minimum bid"); require(msg.sender == tx.origin, "No contract bidding"); require( msg.value > auction.highestBid.amount + (auction.highestBid.amount / 20), "Bid must be > 5% greater than current bid" ); Bid memory previousBid = auction.highestBid; // set new bidder auction.highestBid = Bid({ bidder: payable(msg.sender), amount: msg.value }); // refund previous bidder if (auction.endTime != 0) { require(block.timestamp < auction.endTime, "Auction ended"); if ( block.timestamp + project.auctionExtenderTimeFrame > auction.endTime ) { auction.endTime += project.auctionExtension; } previousBid.bidder.transfer(previousBid.amount); } else { // first bid unchecked { auction.endTime = uint56(block.timestamp) + project.auctionDuration; } } emit NewBidPlaced(auction.highestBid); } /** * @notice Allows a user to reveal the next piece and place a bid in a single transaction. * @dev This function combines the actions of revealing the next piece in the auction (if any) * and placing a bid on it. It is designed to streamline user interactions with the contract * by reducing the number of transactions they need to send. * This function should only be called if it's time to reveal a new piece and the caller * wants to place a bid immediately after the reveal. * The function calls `revealNextPiece` followed by `placeBid`, inheriting their logical checks * and effects. * @notice Ensure that you send enough Ether to cover the bid amount when calling this function. * @notice This function will fail if called when it's not time to reveal a new piece, * or if the bid conditions are not met (e.g., bid too low). */ function revealAndBid() public payable { revealNextPiece(); placeBid(); } /** * @dev Internally claims the item for the highest bidder after the auction ends. * This function is primarily used during the reveal process to ensure the item is claimed * and the _owners.length is updated if the item wasn't previously claimed. */ function _claim() private { require(auction.endTime != 0, "Auction not started"); if (auction.highestBid.bidder == tokenIdToRevealer[auction.tokenId]) { uint256 refund = (auction.highestBid.amount / 10000) * (project.revealerDiscount); _withdrawable += auction.highestBid.amount - refund; auction.highestBid.bidder.transfer(refund); } else { _withdrawable += auction.highestBid.amount; } delete auction.tokenId; _mint(auction.highestBid.bidder, auction.tokenId); } /** * @notice Allows the highest bidder to claim their item after the auction ends. * @dev This is the public version of the _claim function. */ function claim() public { require(auction.endTime != 0, "Auction not started"); require(block.timestamp > auction.endTime, "Auction not concluded"); require(auction.claimed == false, "Already claimed"); if (auction.highestBid.bidder == tokenIdToRevealer[auction.tokenId]) { uint256 refund = (auction.highestBid.amount / 10000) * (project.revealerDiscount); _withdrawable += auction.highestBid.amount - refund; auction.highestBid.bidder.transfer(refund); } else { _withdrawable += auction.highestBid.amount; } auction.claimed = true; delete auction.tokenId; _mint(auction.highestBid.bidder, auction.tokenId); } /** * @notice Check whether a given address is on the allowlist and whether it has already claimed a token. * @dev Returns two boolean values. The first indicates whether the address is on the allowlist, and the second indicates whether the address has already claimed a token. * @param a The address to check. * @param proof The proof of inclusion in the project's Merkle tree for the given address. * @return isOnList Whether the address is on the allowlist. * @return hasClaimed Whether the address has already claimed a token. */ function getAllowListAndClaimStatus( address a, bytes32[] memory proof ) public view returns (bool, bool) { bytes32 hash = keccak256(abi.encodePacked(a)); bool isOnList = MerkleProofUpgradeable.verify( proof, project.merkleRoot, hash ); bool hasClaimed = _addressToClaimed[a]; return (isOnList, hasClaimed); } /** * @notice Create a hash for the given tokenId, blockNumber and sender. * @param tokenId The ID of the token. * @param sender The address of the sender. * @return The resulting hash. */ function createHash( uint256 tokenId, address sender ) private view returns (bytes32) { unchecked { return keccak256( abi.encodePacked( tokenId, sender, blockhash(block.number - 1), blockhash(block.number - 2), blockhash(block.number - 4), block.prevrandao, block.coinbase ) ); } } /** * @notice Get the hash associated with a given tokenId. * @param _id The ID of the token. * @return The hash associated with the given tokenId. */ function tokenHash(uint256 _id) public view returns (bytes32) { return tokenIdToHash[_id]; } /** * @notice Withdraw funds from the contract * @dev Transfers a percentage of the balance to the 8NAPART address and optionally a third party, the rest to the artist address. */ function withdraw() public { require( (msg.sender == project.eightNap || msg.sender == project.artistAddress || msg.sender == project.twoFiveSix), "Not allowed" ); uint256 balance = _withdrawable; require(balance > 0, "Balance is zero"); uint256 eightNapBalance = (balance * project.eightNapShare) / 10000; uint256 twoFiveSixBalance = (balance * project.twoFiveSixShare) / 10000; uint256 artistBalance = balance - eightNapBalance - twoFiveSixBalance; delete _withdrawable; project.eightNap.transfer(eightNapBalance); project.twoFiveSix.transfer(twoFiveSixBalance); project.artistAddress.transfer(artistBalance); } function walletOfOwner( address _owner ) public view returns (uint256[] memory) { uint256 tokenCount = balanceOf(_owner); if (tokenCount == 0) return new uint256[](0); uint256[] memory tokensId = new uint256[](tokenCount); for (uint256 i; i < tokenCount; i++) { tokensId[i] = tokenOfOwnerByIndex(_owner, i); } return tokensId; } function batchTransferFrom( address _from, address _to, uint256[] memory _tokenIds ) public { for (uint256 i; i < _tokenIds.length; i++) { transferFrom(_from, _to, _tokenIds[i]); } } function batchSafeTransferFrom( address _from, address _to, uint256[] memory _tokenIds, bytes memory data_ ) public { for (uint256 i; i < _tokenIds.length; i++) { safeTransferFrom(_from, _to, _tokenIds[i], data_); } } function isOwnerOf( address account, uint256[] calldata _tokenIds ) external view returns (bool) { for (uint256 i; i < _tokenIds.length; ++i) { if (_owners[_tokenIds[i]] != account) return false; } return true; } function _mint(address to, uint256 tokenId) internal virtual override { _owners.push(to); emit Transfer(address(0), to, tokenId); } /** * @notice Calculates the royalty information for a given sale. * @dev Implements the required royaltyInfo function for the ERC2981 standard. * @param _salePrice The sale price of the token being sold. * @return receiver The address of the royalty recipient. * @return royaltyAmount The amount of royalty to be paid. */ function royaltyInfo( uint256, uint256 _salePrice ) external view returns (address receiver, uint256 royaltyAmount) { return (project.royaltyAddress, (_salePrice * project.royalty) / 10000); } /** * @notice Converts a bytes16 value to its hexadecimal representation as a bytes32 value. * @param data The bytes16 value to convert. * @return result The hexadecimal representation of the input value as a bytes32 value. */ function toHex16(bytes16 data) internal pure returns (bytes32 result) { result = (bytes32(data) & 0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000) | ((bytes32(data) & 0x0000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000) >> 64); result = (result & 0xFFFFFFFF000000000000000000000000FFFFFFFF000000000000000000000000) | ((result & 0x00000000FFFFFFFF000000000000000000000000FFFFFFFF0000000000000000) >> 32); result = (result & 0xFFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000) | ((result & 0x0000FFFF000000000000FFFF000000000000FFFF000000000000FFFF00000000) >> 16); result = (result & 0xFF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000) | ((result & 0x00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000) >> 8); result = ((result & 0xF000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000) >> 4) | ((result & 0x0F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F00) >> 8); result = bytes32( 0x3030303030303030303030303030303030303030303030303030303030303030 + uint256(result) + (((uint256(result) + 0x0606060606060606060606060606060606060606060606060606060606060606) >> 4) & 0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F) * 7 ); } /** * @dev Converts a bytes32 value to its hexadecimal representation as a string. * @param data The bytes32 value to convert. * @return The hexadecimal representation of the bytes32 value, as a string. */ function toHex(bytes32 data) private pure returns (string memory) { return string( abi.encodePacked( "0x", toHex16(bytes16(data)), toHex16(bytes16(data << 128)) ) ); } /** * @notice Returns a string containing base64 encoded HTML code which renders the artwork associated with the given tokenId directly from chain. * @dev This function reads libraries from the storage and uses them to generate the HTML code for the artwork. * @param tokenId The ID of the token whose artwork will be generated. * @return artwork A string containing the base64 encoded HTML code for the artwork. */ function tokenHTML( uint256 tokenId ) public view returns (string memory artwork) { require(tokenHash(tokenId) != bytes32(0), "Token not found"); string memory artScript; string memory libraryScripts; if (project.libraryScripts != address(0)) { LibraryScript[] memory librariesArray = abi.decode( SSTORE2.read(project.libraryScripts), (LibraryScript[]) ); for (uint256 l; l < librariesArray.length; l++) { IFileStore fileStore = IFileStore(librariesArray[l].fileStore); libraryScripts = string.concat( libraryScripts, "await ls256('", fileStore.getFile(librariesArray[l].fileName).read(), "');" ); } } for (uint256 i; i < project.artScripts.length; i++) { IArtScript artscriptToGet = IArtScript(project.artScripts[i]); artScript = string.concat(artScript, artscriptToGet.artScript()); } return string.concat( "data:text/html;base64,", Base64Upgradeable.encode( abi.encodePacked( "<html><head><script>let inputData={'tokenId': ", StringsUpgradeable.toString(tokenId), ",'hash': '", toHex(tokenHash(tokenId)), "'", "};", "</script>", "<meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1'><style type='text/css'>html{height:100%;width:100%;}body{height:100%;width:100%;margin:0;padding:0;background-color:#000000;}canvas{display:block;max-width:100%;max-height:100%;padding:0;margin:auto;display:block;position:absolute;top:0;bottom:0;left:0;right:0;object-fit:contain;}</style>", "</head><body><script defer>async function ls256(e){let t=new TextDecoder,a=window.atob(e),n=a.length,r=new Uint8Array(n);for(var o=0;o<n;o++)r[o]=a.charCodeAt(o);let d=r.buffer;let c=new ReadableStream({start(e){e.enqueue(d),e.close()}}).pipeThrough(new DecompressionStream('gzip')),i=await new Response(c),p=await i.arrayBuffer(),l=await t.decode(p),s=document.createElement('script');s.type='text/javascript',s.appendChild(document.createTextNode(l)),document.body.appendChild(s)};async function la256(){", libraryScripts, "await ls256('", artScript, "');" "};la256();</script></body></html>" ) ) ); } /** * @notice Returns the metadata of the token with the given ID, including name, artist, description, license, image and animation URL, and attributes. * @dev It returns a base64 encoded JSON object which conforms to the ERC721 metadata standard. * @param _tokenId The ID of the token to retrieve metadata for. * @return A base64 encoded JSON object that contains the metadata of the given token. */ function tokenURI( uint256 _tokenId ) public view override returns (string memory) { require(tokenHash(_tokenId) != bytes32(0), "Token not found"); return string( abi.encodePacked( project.baseURI, StringsUpgradeable.toString(_tokenId) ) ); } /** * @notice Allows to set the image base URL for the project (owner) * @dev Only callable by the owner * @param _baseURI String representing the base URL for images */ function setBaseURI(string calldata _baseURI) public onlyOwner { project.baseURI = _baseURI; emit BaseURISet(_baseURI); } /** * @notice Sets the maximum number of tokens that can be minted for the project (owner) * @dev Only the owner of the contract can call this function. * @dev The new maximum supply must be greater than the current number of tokens minted * and less than the current maximum supply * @param _maxSupply The new maximum number of tokens that can be minted */ function setMaxSupply(uint24 _maxSupply) public onlyOwner { require(_maxSupply > _owners.length, "Too low"); require(_maxSupply < project.maxSupply, "Too high"); project.maxSupply = _maxSupply + 1; // We always set maxSupply one higher for gas savings during mint emit MaxSupplySet(_maxSupply); } /** * @notice Allows to set the art scripts for the project * @param _artScripts Array of addresses representing the art scripts */ function setArtScripts(address[] calldata _artScripts) public onlyOwner { project.artScripts = _artScripts; emit ArtScriptsSet(); } /** * @notice Allows to set the library scripts for the project * @param _libraries Array of LibraryScript objects representing the library scripts */ function setLibraryScripts( LibraryScript[] calldata _libraries ) public onlyOwner { project.libraryScripts = SSTORE2.write(abi.encode(_libraries)); emit LibraryScriptsSet(); } /** * @notice Returns the mintpass holder price for the project * @dev This function is view only * @return uint256 Representing the presale price for the project */ function getmintPassHolderPrice() external view returns (uint256) { return project.mintPassHolderPrice; } /** * @notice Returns the allowlist price for the project * @dev This function is view only * @return uint256 Representing the presale price for the project */ function getAllowListPrice() external view returns (uint256) { return project.allowListPrice; } /** * @notice Returns the public price for the project * @dev This function is view only * @return uint256 Representing the presale price for the project */ function getPublicPrice() external view returns (uint256) { return project.publicPrice; } /** * @notice Returns the address of the ArtInfo contract used in the project * @dev This function is view only * @return address Representing the address of the ArtInfo contract */ function getArtInfo() external view returns (address) { return project.artInfo; } /** * @notice Returns an array with the addresses storing the art script used in the project * @dev This function is view only * @return address[] Array of addresses storing the art script used in the project */ function getArtScripts() external view returns (address[] memory) { return project.artScripts; } /** * @notice Returns the maximum number of tokens that can be minted for the project * @dev This function is view only * @return uint256 Representing the maximum number of tokens that can be minted */ function getMaxSupply() external view returns (uint256) { return project.maxSupply - 1; } /** * @notice Returns the timestamp of the bidding start for the project * @dev This function is view only * @return uint256 Representing the timestamp of the bidding start */ function getBiddingStartTimeStamp() external view returns (uint256) { return project.biddingStartTimeStamp; } /** * @notice Returns the timestamp of the bidding start for the project * @dev This function is view only * @return uint256 Representing the timestamp of the bidding start */ function getPublicStartTimeStamp() external view returns (uint256) { return project.publicStartTimeStamp; } /** * @notice Returns the timestamp of the allowlist start for the project * @dev This function is view only * @return uint256 Representing the timestamp of the allowlist start */ function getallowListStartTimeStamp() external view returns (uint256) { return project.allowListStartTimeStamp; } /** * @notice Returns the timestamp of the mintpass start for the project * @dev This function is view only * @return uint256 Representing the timestamp of the allowlist start */ function getMintPassStartTimeStamp() external view returns (uint256) { return project.mintPassStartTimeStamp; } /** * @notice Retrieves the number of tokens left available for auction. * @dev This getter function returns the current count of tokens that can still be minted during the auction phase. * @return The number of tokens left for auction. */ function getSupplyLeftForAuction() public view returns (uint32) { return project.supplyLeftForAuction; } /** * @notice Returns the current status of the minting phases and the auction. * @dev This function provides a JSON-like string representation of the current status * of various stages in the contract: Mint Pass Mint, Allow List Mint, and Auction. * It checks the current time against the pre-set timestamps for each phase * and determines their status. * The statuses are represented as integers: * - 0: Not started * - 1: Open * - 2: Ended * @return A string in a JSON-like format that includes the status of each phase and * the remaining time for the current phase (if applicable). * @notice The returned string needs to be parsed on the client side to extract relevant information. */ function getStatus() public view returns (string memory) { uint256 currentTime = block.timestamp; uint256 mintPassStatus = 0; // Not started uint256 allowListStatus = 0; // Not started uint256 publicStatus = 0; // Not started uint256 auctionStatus = 0; // Not started uint256 currentBidAmount = 0; address currentBidder = address(0); address revealerAddress = tokenIdToRevealer[_owners.length]; uint256 ownersLengthPlusOne = _owners.length + 1; // Cached for multiple uses uint256 maxSupplyForAuction = project.maxSupply - project.supplyLeftForAuction; // Cached for multiple uses // Check Mint Pass Mint status if ( currentTime > project.mintPassStartTimeStamp && currentTime < project.allowListStartTimeStamp ) { mintPassStatus = 1; // Open } else if (currentTime >= project.allowListStartTimeStamp) { mintPassStatus = 2; // Ended } // Check Allow List Mint status if ( currentTime > project.allowListStartTimeStamp && (currentTime < project.biddingStartTimeStamp || currentTime < project.publicStartTimeStamp) ) { allowListStatus = 1; // Open } else if ( currentTime >= project.biddingStartTimeStamp && currentTime >= project.publicStartTimeStamp ) { allowListStatus = 2; // Ended } /* require(totalSupply + count < (project.maxSupply - project.supplyLeftForAuction), "Not available"); */ if ( project.publicStartTimeStamp != 0 && currentTime > project.publicStartTimeStamp && (ownersLengthPlusOne < (maxSupplyForAuction)) ) { publicStatus = 1; // Open } else if ( project.publicStartTimeStamp != 0 && (ownersLengthPlusOne >= (maxSupplyForAuction)) ) { publicStatus = 2; //Ended } if ( (project.publicStartTimeStamp == 0 && currentTime > project.biddingStartTimeStamp) || (ownersLengthPlusOne >= (maxSupplyForAuction)) ) // Check Auction status { auctionStatus = 1; // Open if (currentTime < auction.endTime) { currentBidAmount = auction.highestBid.amount; currentBidder = auction.highestBid.bidder; } else { auctionStatus = 2; // Ended } } return string( abi.encodePacked( "{", '"mintPassStatus":', StringsUpgradeable.toString(mintPassStatus), ",", '"allowListStatus":', StringsUpgradeable.toString(allowListStatus), ",", '"auctionStatus":', StringsUpgradeable.toString(auctionStatus), ",", '"publicStatus":', StringsUpgradeable.toString(publicStatus), ",", '"auctionEndTime":', StringsUpgradeable.toString(auction.endTime), ",", '"currentBidAmount":', StringsUpgradeable.toString(currentBidAmount), ",", '"currentBidder":"', StringsUpgradeable.toHexString( uint256(uint160(currentBidder)), 20 ), '","revealer":"', revealerAddress == address(0) ? "" : StringsUpgradeable.toHexString( uint256(uint160(revealerAddress)), 20 ), '"', "}" ) ); } } interface IArtScript { function artScript() external pure returns (string memory); } interface IArtInfo { function artist() external pure returns (string memory); function description() external pure returns (string memory); function license() external pure returns (string memory); } interface IFileStore { function getFile( string memory filename ) external view returns (File memory file); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../IERC721Upgradeable.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721EnumerableUpgradeable is IERC721Upgradeable { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721Upgradeable.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721MetadataUpgradeable is IERC721Upgradeable { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// 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 IERC721ReceiverUpgradeable { /** * @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.9.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721Upgradeable is IERC165Upgradeable { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/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 (last updated v4.7.0) (utils/Base64.sol) pragma solidity ^0.8.0; /** * @dev Provides a set of functions to operate with Base64 strings. * * _Available since v4.5._ */ library Base64Upgradeable { /** * @dev Base64 Encoding/Decoding Table */ string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * @dev Converts a `bytes` to its Bytes64 `string` representation. */ function encode(bytes memory data) internal pure returns (string memory) { /** * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol */ if (data.length == 0) return ""; // Loads the table into memory string memory table = _TABLE; // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter // and split into 4 numbers of 6 bits. // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up // - `data.length + 2` -> Round up // - `/ 3` -> Number of 3-bytes chunks // - `4 *` -> 4 characters for each chunk string memory result = new string(4 * ((data.length + 2) / 3)); /// @solidity memory-safe-assembly assembly { // Prepare the lookup table (skip the first "length" byte) let tablePtr := add(table, 1) // Prepare result pointer, jump over length let resultPtr := add(result, 32) // Run over the input, 3 bytes at a time for { let dataPtr := data let endPtr := add(data, mload(data)) } lt(dataPtr, endPtr) { } { // Advance 3 bytes dataPtr := add(dataPtr, 3) let input := mload(dataPtr) // To write each character, shift the 3 bytes (18 bits) chunk // 4 times in blocks of 6 bits for each character (18, 12, 6, 0) // and apply logical AND with 0x3F which is the number of // the previous character in the ASCII table prior to the Base64 Table // The result is then added to the table to get the character to write, // and finally write it in the result pointer but with a left shift // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F)))) resultPtr := add(resultPtr, 1) // Advance } // When data `bytes` is not exactly 3 bytes long // it is padded with `=` characters at the end switch mod(mload(data), 3) case 1 { mstore8(sub(resultPtr, 1), 0x3d) mstore8(sub(resultPtr, 2), 0x3d) } case 2 { mstore8(sub(resultPtr, 1), 0x3d) } } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates merkle trees that are safe * against this attack out of the box. */ library MerkleProofUpgradeable { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library MathUpgradeable { 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) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 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 256, 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 << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMathUpgradeable { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/MathUpgradeable.sol"; import "./math/SignedMathUpgradeable.sol"; /** * @dev String operations. */ library StringsUpgradeable { 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 = MathUpgradeable.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 `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMathUpgradeable.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, MathUpgradeable.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); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; library Address { function isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library Bytecode { error InvalidCodeAtRange(uint256 _size, uint256 _start, uint256 _end); /** @notice Generate a creation code that results on a contract with `_code` as bytecode @param _code The returning value of the resulting `creationCode` @return creationCode (constructor) for new contract */ function creationCodeFor(bytes memory _code) internal pure returns (bytes memory) { /* 0x00 0x63 0x63XXXXXX PUSH4 _code.length size 0x01 0x80 0x80 DUP1 size size 0x02 0x60 0x600e PUSH1 14 14 size size 0x03 0x60 0x6000 PUSH1 00 0 14 size size 0x04 0x39 0x39 CODECOPY size 0x05 0x60 0x6000 PUSH1 00 0 size 0x06 0xf3 0xf3 RETURN <CODE> */ return abi.encodePacked( hex"63", uint32(_code.length), hex"80_60_0E_60_00_39_60_00_F3", _code ); } /** @notice Returns the size of the code on a given address @param _addr Address that may or may not contain code @return size of the code on the given `_addr` */ function codeSize(address _addr) internal view returns (uint256 size) { assembly { size := extcodesize(_addr) } } /** @notice Returns the code of a given address @dev It will fail if `_end < _start` @param _addr Address that may or may not contain code @param _start number of bytes of code to skip on read @param _end index before which to end extraction @return oCode read from `_addr` deployed bytecode Forked from: https://gist.github.com/KardanovIR/fe98661df9338c842b4a30306d507fbd */ function codeAt( address _addr, uint256 _start, uint256 _end ) internal view returns (bytes memory oCode) { uint256 csize = codeSize(_addr); if (csize == 0) return bytes(""); if (_start > csize) return bytes(""); if (_end < _start) revert InvalidCodeAtRange(csize, _start, _end); unchecked { uint256 reqSize = _end - _start; uint256 maxSize = csize - _start; uint256 size = maxSize < reqSize ? maxSize : reqSize; assembly { // allocate output byte array - this could also be done without assembly // by using o_code = new bytes(size) oCode := mload(0x40) // new "memory end" including padding mstore( 0x40, add(oCode, and(add(add(size, 0x20), 0x1f), not(0x1f))) ) // store length in memory mstore(oCode, size) // actually retrieve the code, this needs assembly extcodecopy(_addr, add(oCode, 0x20), _start, size) } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import "./ERC721Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721EnumerableUpgradeable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account but rips out the core of the gas-wasting processing that comes from OpenZeppelin. */ abstract contract ERC721EnumerableUpgradeable is ERC721Upgradeable, IERC721EnumerableUpgradeable { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165Upgradeable, ERC721Upgradeable) returns (bool) { return interfaceId == type(IERC721EnumerableUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _owners.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require( index < _owners.length, "ERC721Enumerable: global index out of bounds" ); return index; } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256 tokenId) { require( index < balanceOf(owner), "ERC721Enumerable: owner index out of bounds" ); uint256 count; for (uint256 i; i < _owners.length; i++) { if (owner == _owners[i]) { if (count == index) return i; else count++; } } revert("ERC721Enumerable: owner index out of bounds"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol"; import "./Address.sol"; abstract contract ERC721Upgradeable is ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable { using Address for address; using StringsUpgradeable for uint256; string private _name; string private _symbol; // Mapping from token ID to owner address address[] internal _owners; mapping(uint256 => address) private _tokenApprovals; mapping(address => mapping(address => bool)) private _operatorApprovals; function __ERC721_init( string memory name_, string memory symbol_ ) internal onlyInitializing { __ERC721_init_unchained(name_, symbol_); } function __ERC721_init_unchained( string memory name_, string memory symbol_ ) internal onlyInitializing { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface( bytes4 interfaceId ) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) { return interfaceId == type(IERC721Upgradeable).interfaceId || interfaceId == type(IERC721MetadataUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf( address owner ) public view virtual override returns (uint256) { require( owner != address(0), "ERC721: balance query for the zero address" ); uint256 count; for (uint256 i; i < _owners.length; ++i) { if (owner == _owners[i]) ++count; } return count; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf( uint256 tokenId ) public view virtual override returns (address) { address owner = _owners[tokenId]; require( owner != address(0), "ERC721: owner query for nonexistent token" ); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721Upgradeable.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved( uint256 tokenId ) public view virtual override returns (address) { require( _exists(tokenId), "ERC721: approved query for nonexistent token" ); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll( address operator, bool approved ) public virtual override { require(operator != _msgSender(), "ERC721: approve to caller"); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll( address owner, address operator ) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require( _isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved" ); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public virtual override { require( _isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved" ); _safeTransfer(from, to, tokenId, _data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `_data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory _data ) internal virtual { _transfer(from, to, tokenId); require( _checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return tokenId < _owners.length && _owners[tokenId] != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner( address spender, uint256 tokenId ) internal view virtual returns (bool) { require( _exists(tokenId), "ERC721: operator query for nonexistent token" ); address owner = ERC721Upgradeable.ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory _data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _owners.push(to); emit Transfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721Upgradeable.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _owners[tokenId] = address(0); emit Transfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require( ERC721Upgradeable.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own" ); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _owners[tokenId] = to; emit Transfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits a {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { if (to.isContract()) { try IERC721ReceiverUpgradeable(to).onERC721Received( _msgSender(), from, tokenId, _data ) returns (bytes4 retval) { return retval == IERC721ReceiverUpgradeable.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert( "ERC721: transfer to non ERC721Receiver implementer" ); } else { assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; /** * @title EthFS File * @notice A representation of an onchain file, composed of slices of contract bytecode and utilities to construct the file contents from those slices. * @dev For best gas efficiency, it's recommended using `File.read()` as close to the output returned by the contract call as possible. Lots of gas is consumed every time a large data blob is passed between functions. */ /** * @dev Represents a reference to a slice of bytecode in a contract */ struct BytecodeSlice { address pointer; uint32 start; uint32 end; } /** * @dev Represents a file composed of one or more bytecode slices */ struct File { // Total length of file contents (sum of all slice sizes). Useful when you want to use DynamicBuffer to build the file contents from the slices. uint256 size; BytecodeSlice[] slices; } // extend File struct with read functions using {read} for File global; using {readUnchecked} for File global; /** * @dev Error thrown when a slice is out of the bounds of the contract's bytecode */ error SliceOutOfBounds( address pointer, uint32 codeSize, uint32 sliceStart, uint32 sliceEnd ); /** * @notice Reads the contents of a file by concatenating its slices * @param file The file to read * @return contents The concatenated contents of the file */ function read(File memory file) view returns (string memory contents) { BytecodeSlice[] memory slices = file.slices; bytes4 sliceOutOfBoundsSelector = SliceOutOfBounds.selector; assembly { let len := mload(slices) let size := 0x20 contents := mload(0x40) let slice let pointer let start let end let codeSize for { let i := 0 } lt(i, len) { i := add(i, 1) } { slice := mload(add(slices, add(0x20, mul(i, 0x20)))) pointer := mload(slice) start := mload(add(slice, 0x20)) end := mload(add(slice, 0x40)) codeSize := extcodesize(pointer) if gt(end, codeSize) { mstore(0x00, sliceOutOfBoundsSelector) mstore(0x04, pointer) mstore(0x24, codeSize) mstore(0x44, start) mstore(0x64, end) revert(0x00, 0x84) } extcodecopy(pointer, add(contents, size), start, sub(end, start)) size := add(size, sub(end, start)) } // update contents size mstore(contents, sub(size, 0x20)) // store contents mstore(0x40, add(contents, and(add(size, 0x1f), not(0x1f)))) } } /** * @notice Reads the contents of a file without reverting on unreadable/invalid slices. Skips any slices that are out of bounds or invalid. Useful if you are composing contract bytecode where a contract can still selfdestruct (which would result in an invalid slice) and want to avoid reverts but still output potentially "corrupted" file contents (due to missing data). * @param file The file to read * @return contents The concatenated contents of the file, skipping invalid slices */ function readUnchecked(File memory file) view returns (string memory contents) { BytecodeSlice[] memory slices = file.slices; assembly { let len := mload(slices) let size := 0x20 contents := mload(0x40) let slice let pointer let start let end let codeSize for { let i := 0 } lt(i, len) { i := add(i, 1) } { slice := mload(add(slices, add(0x20, mul(i, 0x20)))) pointer := mload(slice) start := mload(add(slice, 0x20)) end := mload(add(slice, 0x40)) codeSize := extcodesize(pointer) if lt(end, codeSize) { extcodecopy( pointer, add(contents, size), start, sub(end, start) ) size := add(size, sub(end, start)) } } // update contents size mstore(contents, sub(size, 0x20)) // store contents mstore(0x40, add(contents, and(add(size, 0x1f), not(0x1f)))) } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.13; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.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 OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init(address _ownerOnInit) internal onlyInitializing { __Ownable_init_unchained(_ownerOnInit); } function __Ownable_init_unchained(address _ownerOnInit) internal onlyInitializing { _transferOwnership(_ownerOnInit); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { 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); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import "./Bytecode.sol"; library SSTORE2 { error WriteError(); /** @notice Stores `_data` and returns `pointer` as key for later retrieval @dev The pointer is a contract address with `_data` as code @param _data to be written @return pointer Pointer to the written `_data` */ function write(bytes memory _data) internal returns (address pointer) { // Append 00 to _data so contract can't be called // Build init code bytes memory code = Bytecode.creationCodeFor( abi.encodePacked(hex"00", _data) ); // Deploy contract using create assembly { pointer := create(0, add(code, 32), mload(code)) } // Address MUST be non-zero if (pointer == address(0)) revert WriteError(); } /** @notice Reads the contents of the `_pointer` code as data, skips the first byte @dev The function is intended for reading pointers generated by `write` @param _pointer to be read @return data read from `_pointer` contract */ function read(address _pointer) internal view returns (bytes memory) { return Bytecode.codeAt(_pointer, 1, type(uint256).max); } /** @notice Reads the contents of the `_pointer` code as data, skips the first byte @dev The function is intended for reading pointers generated by `write` @param _pointer to be read @param _start number of bytes to skip @return data read from `_pointer` contract */ function read(address _pointer, uint256 _start) internal view returns (bytes memory) { return Bytecode.codeAt(_pointer, _start + 1, type(uint256).max); } /** @notice Reads the contents of the `_pointer` code as data, skips the first byte @dev The function is intended for reading pointers generated by `write` @param _pointer to be read @param _start number of bytes to skip @param _end index before which to end extraction @return data read from `_pointer` contract */ function read( address _pointer, uint256 _start, uint256 _end ) internal view returns (bytes memory) { return Bytecode.codeAt(_pointer, _start + 1, _end + 1); } }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 125, "details": { "yul": true } }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"_size","type":"uint256"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"}],"name":"InvalidCodeAtRange","type":"error"},{"inputs":[],"name":"WriteError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[],"name":"ArtScriptsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"newBaseURI","type":"string"}],"name":"BaseURISet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[],"name":"LibraryScriptsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint24","name":"newMaxSupply","type":"uint24"}],"name":"MaxSupplySet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address payable","name":"bidder","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"indexed":false,"internalType":"struct EightNapOnChainProjectV1.Bid","name":"bid","type":"tuple"}],"name":"NewBidPlaced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"PieceRevealed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"address","name":"a","type":"address"}],"name":"allowListMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"count","type":"uint24"},{"internalType":"address","name":"a","type":"address"}],"name":"artistMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"batchSafeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"batchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"a","type":"address"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"getAllowListAndClaimStatus","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowListPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getArtInfo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getArtScripts","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBiddingStartTimeStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mintPassId","type":"uint256"}],"name":"getMintPassMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintPassStartTimeStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPublicPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPublicStartTimeStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStatus","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupplyLeftForAuction","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getallowListStartTimeStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getmintPassHolderPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"address[]","name":"artScripts","type":"address[]"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"address","name":"artInfo","type":"address"},{"internalType":"uint56","name":"biddingStartTimeStamp","type":"uint56"},{"internalType":"uint32","name":"maxSupply","type":"uint32"},{"internalType":"address payable","name":"twoFiveSix","type":"address"},{"internalType":"uint96","name":"mintPassHolderPrice","type":"uint96"},{"internalType":"address payable","name":"royaltyAddress","type":"address"},{"internalType":"uint96","name":"minBid","type":"uint96"},{"internalType":"address payable","name":"artistAddress","type":"address"},{"internalType":"uint24","name":"revealerDiscount","type":"uint24"},{"internalType":"uint24","name":"royalty","type":"uint24"},{"internalType":"uint24","name":"eightNapShare","type":"uint24"},{"internalType":"uint24","name":"twoFiveSixShare","type":"uint24"},{"internalType":"address payable","name":"eightNap","type":"address"},{"internalType":"uint56","name":"mintPassStartTimeStamp","type":"uint56"},{"internalType":"uint32","name":"auctionDuration","type":"uint32"},{"internalType":"address","name":"libraryScripts","type":"address"},{"internalType":"uint56","name":"allowListStartTimeStamp","type":"uint56"},{"internalType":"uint32","name":"auctionExtension","type":"uint32"},{"internalType":"address","name":"mintPassAddress","type":"address"},{"internalType":"uint56","name":"publicStartTimeStamp","type":"uint56"},{"internalType":"uint32","name":"auctionExtenderTimeFrame","type":"uint32"},{"internalType":"uint96","name":"allowListPrice","type":"uint96"},{"internalType":"uint96","name":"publicPrice","type":"uint96"},{"internalType":"uint32","name":"supplyLeftForAuction","type":"uint32"}],"internalType":"struct EightNapOnChainProjectV1.Project","name":"_p","type":"tuple"},{"internalType":"address","name":"_libraryScripts","type":"address"}],"name":"initProject","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"isOwnerOf","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"mintPassIds","type":"uint256[]"}],"name":"mintPassMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"placeBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"a","type":"address"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealAndBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"revealNextPiece","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_artScripts","type":"address[]"}],"name":"setArtScripts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fileStore","type":"address"},{"internalType":"string","name":"fileName","type":"string"}],"internalType":"struct EightNapOnChainProjectV1.LibraryScript[]","name":"_libraries","type":"tuple[]"}],"name":"setLibraryScripts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"_maxSupply","type":"uint24"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenHTML","outputs":[{"internalType":"string","name":"artwork","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"tokenHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenIdToHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenIdToRevealer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"walletOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080806040523461001757615f8090816200001d8239f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c806301ffc9a714610392578063025ea63d1461038d57806306fdde0314610388578063081812fc14610383578063095ea7b31461037e5780630eaffa031461037957806318160ddd146103745780631cd500a51461036f5780631f1a7d941461036a5780631ffa01c21461036557806321827eff1461036057806323b872dd1461035b57806325161d11146103565780632a55205a146103515780632f745c591461034c578063322736ba1461034757806334e333951461034257806334ecc48f1461033d578063363e86fe146103385780633ccfd60b1461033357806342842e0e1461032e57806342f74cd714610329578063438b63001461032457806346fca9aa1461031f5780634c0f38c21461031a5780634d44660c146103155780634e43663f146103105780634e69d5601461030b5780634e71d92d146103065780634f6ccce71461030157806355f804b3146102fc5780635a4fee30146102f7578063621a1f74146102c55780636352211e146102f257806370a08231146102ed578063715018a6146102e857806378aa7d38146102e35780638da5cb5b146102de57806395d89b41146102d95780639bb22b40146102d45780639df742d7146102cf578063a22cb465146102ca578063a3864397146102c5578063a7a50365146102c0578063b79bebaf146102bb578063b88d4fde146102b6578063c1b8ce2e146102b1578063c87b56dd146102ac578063ce67764c146102a7578063ce6df2b9146102a2578063e985e9c51461029d578063ecfc7ecc14610298578063ed6f452014610293578063f2fde38b1461028e578063f3993d11146102895763fe0d8aac1461028457600080fd5b612d71565b612cf1565b612c57565b612c2d565b612c19565b612bb1565b612ac7565b6129ea565b61291f565b6128eb565b612895565b612161565b612140565b611b86565b612054565b611e61565b611e3a565b611d96565b611d6d565b611c58565b611bf7565b611bd0565b611bb2565b611af8565b6118f6565b611873565b611728565b611272565b611248565b6111f6565b6111c1565b61119a565b611131565b611108565b6110e0565b610f66565b610f3c565b610f15565b610e66565b610cac565b610c79565b610c35565b610a2f565b610a06565b610893565b610819565b6107ef565b6107c5565b6107a7565b6106cc565b6105ce565b61058d565b6104ad565b610436565b6103ae565b6001600160e01b03198116036103a957565b600080fd5b346103a95760203660031901126103a95760206004356103cd81610397565b63ffffffff60e01b1663780e9d6360e01b81149081156103f3575b506040519015158152f35b6380ac58cd60e01b811491508115610425575b8115610414575b50386103e8565b6301ffc9a760e01b1490503861040d565b635b5e139f60e01b81149150610406565b346103a95760003660031901126103a95761044f614084565b005b60005b8381106104645750506000910152565b8181015183820152602001610454565b9060209161048d81518092818552858086019101610451565b601f01601f1916010190565b9060206104aa928181520190610474565b90565b346103a95760008060031936011261058a57604051816065546104cf81612f24565b808452906001908181169081156105625750600114610509575b610505846104f981880382610dc1565b60405191829182610499565b0390f35b60658352602094507f8ff97419363ffd7000167f130ef7168fbea05faf9251824ca5043f113cc6a7c75b82841061054f5750505081610505936104f992820101936104e9565b8054858501870152928501928101610533565b61050596506104f99450602092508593915060ff191682840152151560051b820101936104e9565b80fd5b346103a95760203660031901126103a95760206105ab600435615737565b6040516001600160a01b039091168152f35b6001600160a01b038116036103a957565b346103a95760403660031901126103a9576004356105eb816105bd565b6024356105f78161562f565b916001600160a01b0380841690821681146106705761044f93610624913314908115610629575b506156ca565b615b33565b6001600160a01b0316600090815260696020526040902061066a91506106639033905b9060018060a01b0316600052602052604060002090565b5460ff1690565b3861061e565b60405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608490fd5b62ffffff8116036103a957565b346103a95760403660031901126103a9576004356106e9816106bf565b602435906106f6826105bd565b61070b60018060a01b03606a54163314613a10565b62ffffff6067549116908181018082116107a25760a654610737919060d81c63ffffffff165b11613ab1565b61074360058310613aea565b60005b82811061074f57005b8061079c600192840161078161077b61076f60a95460018060a01b031690565b6001600160a01b031690565b82614735565b61079582600052609d602052604060002090565b558661494b565b01610746565b613252565b346103a95760003660031901126103a9576020606754604051908152f35b346103a95760003660031901126103a957602066ffffffffffffff60a65460a01c16604051908152f35b346103a95760003660031901126103a957602066ffffffffffffff60ab5460a01c16604051908152f35b60003660031901126103a95761082d614084565b61044f6143d5565b9181601f840112156103a9578235916001600160401b0383116103a9576020808501948460051b0101116103a957565b60206003198201126103a957600435906001600160401b0382116103a95761088f91600401610835565b9091565b346103a9576108a136610865565b9060018060a01b036108b881606a54163314613a10565b6040928351928484019082602092838088015252606085019560608460051b8701019682956000935b868510610950576109296109078a610902818e03601f198101835282610dc1565b615e12565b60ab80546001600160a01b0319166001600160a01b0392909216919091179055565b7fd6a2280fab4cc808ebb209359e38f6c624e9567ae7b4bb53569ce27639c26b79600080a1005b9091929394959698605f198982030184528935603e19833603018112156103a957820183813561097f816105bd565b16825287810135601e19823603018112156103a9570187810190356001600160401b0381116103a95780360382136103a9576109c88992839289868186600199015201916151c7565b9b0194019501939296959491906108e1565b60609060031901126103a9576004356109f2816105bd565b906024356109ff816105bd565b9060443590565b346103a95761044f610a17366109da565b91610a2a610a2584336158f6565b6157ba565b6159d2565b610a3836610865565b610a67610a60610a5460aa5466ffffffffffffff9060a01c1690565b66ffffffffffffff1690565b4211613daf565b610a8a610a83610a5460ab5466ffffffffffffff9060a01c1690565b4210613dfb565b60675491610afb610ab5610aaf610aa360a75460a01c90565b6001600160601b031690565b84613296565b610adc610ac28587613aa4565b60a6546107319060d81c63ffffffff165b63ffffffff1690565b610ae7841515613e3e565b610af360058510613aea565b341015613c8d565b610b06323314613cd2565b60ac54610b1b906001600160a01b031661076f565b90610b293460a0540160a055565b6001600160a01b039091169060005b838110610b4157005b610b4c818584613e7e565b6040516331a9108f60e11b8152903560048201529060208083602481885afa8015610c3057610bfe93610bf992600092610c03575b5050610b8d8389613aa4565b90610bb9610bb4610bb0610ba2878c8b613e7e565b356001901b609f5416151590565b1590565b613eaf565b610bd5610bc7858a89613e7e565b356001901b609f5417609f55565b610bdf3383614735565b610bf383600052609d602052604060002090565b5561494b565b613d71565b610b38565b610c229250803d10610c29575b610c1a8183610dc1565b810190613e8e565b3880610b81565b503d610c10565b613ea3565b346103a95760403660031901126103a957604060018060a01b0360a85416612710610c6c62ffffff60a95460b81c16602435613296565b0482519182526020820152f35b346103a95760403660031901126103a9576020610ca4600435610c9b816105bd565b6024359061538c565b604051908152f35b346103a95760008060031936011261058a57604051809160a454908183526020809301809260a4835284832090835b818110610d385750505084610cf1910385610dc1565b60405193838594850191818652518092526040850193925b828110610d1857505050500390f35b83516001600160a01b031685528695509381019392810192600101610d09565b82546001600160a01b031684529286019260019283019201610cdb565b634e487b7160e01b600052604160045260246000fd5b604081019081106001600160401b03821117610d8657604052565b610d55565b606081019081106001600160401b03821117610d8657604052565b602081019081106001600160401b03821117610d8657604052565b90601f801991011681019081106001600160401b03821117610d8657604052565b60405190610def82610d6b565b565b6001600160401b038111610d865760051b60200190565b81601f820112156103a957803591610e1f83610df1565b92610e2d6040519485610dc1565b808452602092838086019260051b8201019283116103a9578301905b828210610e57575050505090565b81358152908301908301610e49565b346103a95760403660031901126103a957600435610e83816105bd565b6024356001600160401b0381116103a957610ea5610ee3913690600401610e08565b604051606084901b6001600160601b0319166020820190815290610ed681603481015b03601f198101835282610dc1565b5190209060a55490613d14565b6001600160a01b03919091166000908152609c6020908152604091829020548251931515845260ff1615159083015290f35b346103a95760203660031901126103a957602060016004351b609f54161515604051908152f35b346103a95760003660031901126103a95760206001600160601b0360ad5460601c16604051908152f35b346103a95760008060031936011261058a5760aa54610f8d906001600160a01b031661076f565b331480156110c3575b80156110a0575b610fa6906147a8565b610fdd60a054610fb78115156147e2565b82808080610ffe60a95495610ff9610ff1610fe5610fdd62ffffff8b60d01c1685613296565b612710900490565b998a9960e81c84613296565b97889261460a565b61460a565b95611009600060a055565b60aa5461101e906001600160a01b031661076f565b828215611097575bf115610c305760a7548391829182918291611049906001600160a01b031661076f565b82821561108e575bf115610c305760a9548291829182918291611074906001600160a01b031661076f565b828215611085575bf115610c305780f35b506108fc61107c565b506108fc611051565b506108fc611026565b5060a754610fa6906110ba906001600160a01b031661076f565b33149050610f9d565b5060a9546110d9906001600160a01b031661076f565b3314610f96565b346103a95761044f6110f1366109da565b90604051926110ff84610da6565b60008452615820565b346103a95760003660031901126103a95760a6546040516001600160a01b039091168152602090f35b346103a9576020806003193601126103a957611157600435611152816105bd565b614820565b906040519181839283018184528251809152816040850193019160005b82811061118357505050500390f35b835185528695509381019392810192600101611174565b346103a95760003660031901126103a957602063ffffffff60ad5460c01c16604051908152f35b346103a95760003660031901126103a95763ffffffff6000198160a65460d81c16018181116107a25760209160405191168152f35b346103a95760403660031901126103a957600435611213816105bd565b6024356001600160401b0381116103a95760209161123861123e923690600401610835565b916148e2565b6040519015158152f35b346103a95760003660031901126103a957602066ffffffffffffff60ac5460a01c16604051908152f35b346103a95760008060031936011261058a578081908291838081606754936112bd6112b76112aa87600052609e602052604060002090565b546001600160a01b031690565b95613a5b565b9660a654966112ea610ad36112db60ad5463ffffffff9060c01c1690565b63ffffffff8b60d81c16613c3b565b90611304610a5460aa5466ffffffffffffff9060a01c1690565b421180611708575b156116df57506001925b60ab5461132e9060a01c66ffffffffffffff16610a54565b4211806116aa575b1561166457506001985b66ffffffffffffff8061135f60ac5466ffffffffffffff9060a01c1690565b169384159485158091819261165a575b5080611651575b156116305750506001995b84611621575b50508215611616575b50506115a7575b6113af6113a96113a96113b593614eb7565b98614eb7565b95614eb7565b906113dc6113d66113d1610a5460b15466ffffffffffffff1690565b614eb7565b93614eb7565b936001600160a01b03906113f19082166152ba565b95169050806115985750611403612f07565b945b604051607b60f81b602082015297889760218901701136b4b73a2830b9b9a9ba30ba3ab9911d60791b815260110161143c91614bfd565b61144590615244565b711130b63637bba634b9ba29ba30ba3ab9911d60711b815260120161146991614bfd565b61147290615244565b6f1130bab1ba34b7b729ba30ba3ab9911d60811b815260100161149491614bfd565b61149d90615244565b6e11383ab13634b1a9ba30ba3ab9911d60891b8152600f016114be91614bfd565b6114c790615244565b701130bab1ba34b7b722b7322a34b6b2911d60791b81526011016114ea91614bfd565b6114f390615244565b721131bab93932b73a2134b220b6b7bab73a111d60691b815260130161151891614bfd565b61152190615244565b701131bab93932b73a2134b23232b9111d1160791b815260110161154491614bfd565b6d1116113932bb32b0b632b9111d1160911b8152600e0161156491614bfd565b601160f91b8152600101607d60f81b815260010103601f198101825261158a9082610dc1565b604051610505819282610499565b6115a1906152ba565b94611405565b92909196506001966115c4610a5460b15466ffffffffffffff1690565b4210156115fd57505060af54906113b56113af6113a96113a96115f161076f60ae5460018060a01b031690565b965b9350505050611397565b91909296506113b56113af6113a96113a960029a6115f3565b101590503880611390565b60a01c16421192503880611387565b909a9080611647575b156113815760029a50611381565b5083831015611639565b50848410611376565b905042113861136f565b9866ffffffffffffff8960a01c1642101580611689575b156113405760029950611340565b5060ac546116a29060a01c66ffffffffffffff16610a54565b42101561167b565b5066ffffffffffffff8960a01c16421080611336575060ac546116d89060a01c66ffffffffffffff16610a54565b4210611336565b926116f9610a5460ab5466ffffffffffffff9060a01c1690565b42106113165760029350611316565b5060ab546117219060a01c66ffffffffffffff16610a54565b421061130c565b346103a95760008060031936011261058a5761176b60ff60b15461176166ffffffffffffff821661175a8115156145c8565b42116146f1565b60381c1615613bfd565b60ae546001600160a01b031661179361076f6112aa60b054600052609e602052604060002090565b6001600160a01b0391821603611859578180808060af546117f16117ec6117e46117dd6117d36117cb60a95462ffffff9060a01c1690565b62ffffff1690565b6127108604613296565b809461460a565b60a054613aa4565b60a055565b60ae54611806906001600160a01b031661076f565b828215611850575bf115610c305761184d905b60b1805460ff60381b1916600160381b1790555b611837600060b055565b60ae546001600160a01b031660b054911661494b565b80f35b506108fc61180e565b61184d9061186e6117ec60af5460a054613aa4565b611819565b346103a95760203660031901126103a95760043560675481101561189c57602090604051908152f35b60405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608490fd5b346103a9576020806003193601126103a9576001600160401b03906004358281116103a957366023820112156103a95780600401359283116103a957602491368385840101116103a95761195560018060a01b03606a54163314613a10565b6119698461196460a354612f24565b612fba565b600090601f85116001146119dd5750837ff9c7803e94e0d3c02900d8a90893a6d5e90dd04d32a4cfe825520f82bf9f32f694846119cb936000926119d0575b50508160011b906000198360031b1c19161760a3555b60405193849301836151e8565b0390a1005b85010135905084386119a8565b60a360005290601f1985167f60859188cffe297f44dde29f2d2865634621f26215049caeb304ccba566a8b179282905b828210611a715750509185917ff9c7803e94e0d3c02900d8a90893a6d5e90dd04d32a4cfe825520f82bf9f32f6966119cb9410611a55575b5050600181811b0160a3556119be565b8401850135600019600384901b60f8161c191690553880611a45565b8060018596898395978a0101358155019501930190611a0d565b6001600160401b038111610d8657601f01601f191660200190565b929192611ab282611a8b565b91611ac06040519384610dc1565b8294818452818301116103a9578281602093846000960137010152565b9080601f830112156103a9578160206104aa93359101611aa6565b346103a95760803660031901126103a957600435611b15816105bd565b60243590611b22826105bd565b6001600160401b036044358181116103a957611b42903690600401610e08565b906064359081116103a957611b5b903690600401611add565b60005b825181101561044f5780610bf983611b79611b819487613d96565b518888615820565b611b5e565b346103a95760203660031901126103a957600435600052609d6020526020604060002054604051908152f35b346103a95760203660031901126103a95760206105ab60043561562f565b346103a95760203660031901126103a9576020610ca4600435611bf2816105bd565b61557a565b346103a95760008060031936011261058a57606a5481906001600160a01b03811690611c24338314613a10565b6001600160a01b031916606a557f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b346103a9576003196040368201126103a957600435906001600160401b0382116103a9576103809082360301126103a957611cdd602435611c98816105bd565b60005492611cbd60ff8560081c161580958196611d5f575b8115611d3f575b50612e72565b83611cd0600160ff196000541617600055565b611d26575b600401613876565b611ce357005b611cf361ff001960005416600055565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989080602081016119cb565b611d3a61010061ff00196000541617600055565b611cd5565b303b15915081611d51575b5038611cb7565b6001915060ff161438611d4a565b600160ff8216109150611cb0565b346103a95760003660031901126103a957606a546040516001600160a01b039091168152602090f35b346103a95760008060031936011261058a5760405181606654611db881612f24565b808452906001908181169081156105625750600114611de157610505846104f981880382610dc1565b60668352602094507f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e943545b828410611e275750505081610505936104f992820101936104e9565b8054858501870152928501928101611e0b565b346103a95760003660031901126103a95760206001600160601b0360ad5416604051908152f35b60403660031901126103a9576004356001600160401b0381116103a957611e8f61044f913690600401610e08565b602435611e9b816105bd565b611ebe611eb7610a5460ab5466ffffffffffffff9060a01c1690565b4211613b2d565b611f8760a654611f23611f1e66ffffffffffffff95868460a01c164210801561202e575b611eeb90613b79565b60a554604051606088901b6001600160601b0319166020820190815290611f158160348101610ec8565b51902091613d14565b613bbd565b6001600160a01b0383166000908152609c60205260409020611f4e90611f4890610663565b15613bfd565b60675493611f6860ac5466ffffffffffffff9060a01c1690565b16611fef575b63ffffffff611f7c85613a5b565b9160d81c1611613ab1565b611fae611f9c60ad546001600160601b031690565b6001600160601b033491161115613c8d565b611fb9323314613cd2565b6001600160a01b0381166000908152609c60205260409020611fe290805460ff19166001179055565b610bd53460a0540160a055565b612029611ffb85613a5b565b612023610ad361201460ad5463ffffffff9060c01c1690565b63ffffffff8660d81c16613c3b565b11613c51565b611f6e565b50611eeb61204b610a5460ac5466ffffffffffffff9060a01c1690565b42109050611ee2565b346103a95760403660031901126103a957600435612071816105bd565b60243580151581036103a9576001600160a01b038216913383146120ff57816120bc6120cd9233600052606960205260406000209060018060a01b0316600052602052604060002090565b9060ff801983541691151516179055565b604051901515815233907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3190602090a3005b60405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b6044820152606490fd5b346103a95760003660031901126103a957602060a75460a01c604051908152f35b346103a9576020806003193601126103a95760049081359161219861219084600052609d602052604060002090565b5415156149be565b60ab5460609182916001600160a01b0316806127b7575b5060a4546000915b81831061272a575050506121ca84614eb7565b936121df90600052609d602052604060002090565b546121e990614ff5565b6040517f3c68746d6c3e3c686561643e3c7363726970743e6c657420696e7075744461749481019485526d0309ebd93ba37b5b2b724b2139d160951b6020860152948594602e0161223991614bfd565b692c2768617368273a202760b01b8152600a0161225591614bfd565b602760f81b8152600101617d3b60f01b8152600201681e17b9b1b934b83a1f60b91b81526009017f3c6d657461206e616d653d2776696577706f72742720636f6e74656e743d277781527f696474683d6465766963652d77696474682c20696e697469616c2d7363616c6560208201527f3d312c206d6178696d756d2d7363616c653d31273e3c7374796c65207479706560408201527f3d27746578742f637373273e68746d6c7b6865696768743a313030253b77696460608201527f74683a313030253b7d626f64797b6865696768743a313030253b77696474683a60808201527f313030253b6d617267696e3a303b70616464696e673a303b6261636b67726f7560a08201527f6e642d636f6c6f723a233030303030303b7d63616e7661737b646973706c617960c08201527f3a626c6f636b3b6d61782d77696474683a313030253b6d61782d68656967687460e08201527f3a313030253b70616464696e673a303b6d617267696e3a6175746f3b646973706101008201527f6c61793a626c6f636b3b706f736974696f6e3a6162736f6c7574653b746f703a6101208201527f303b626f74746f6d3a303b6c6566743a303b72696768743a303b6f626a6563746101408201527516b334ba1d31b7b73a30b4b71dbe9e17b9ba3cb6329f60511b610160820152610176017f3c2f686561643e3c626f64793e3c7363726970742064656665723e6173796e6381527f2066756e6374696f6e206c733235362865297b6c657420743d6e65772054657860208201527f744465636f6465722c613d77696e646f772e61746f622865292c6e3d612e6c6560408201527f6e6774682c723d6e65772055696e74384172726179286e293b666f722876617260608201527f206f3d303b6f3c6e3b6f2b2b29725b6f5d3d612e63686172436f64654174286f60808201527f293b6c657420643d722e6275666665723b6c657420633d6e657720526561646160a08201527f626c6553747265616d287b73746172742865297b652e656e717565756528642960c08201527f2c652e636c6f736528297d7d292e706970655468726f756768286e657720446560e08201527f636f6d7072657373696f6e53747265616d2827677a69702729292c693d6177616101008201527f6974206e657720526573706f6e73652863292c703d617761697420692e6172726101208201527f617942756666657228292c6c3d617761697420742e6465636f64652870292c736101408201527f3d646f63756d656e742e637265617465456c656d656e742827736372697074276101608201527f293b732e747970653d27746578742f6a617661736372697074272c732e6170706101808201527f656e644368696c6428646f63756d656e742e637265617465546578744e6f64656101a08201527f286c29292c646f63756d656e742e626f64792e617070656e644368696c6428736101c08201527f297d3b6173796e632066756e6374696f6e206c6132353628297b0000000000006101e08201526101fa016126b491614bfd565b6c6177616974206c73323536282760981b8152600d016126d391614bfd565b7f27293b7d3b6c6132353628293b3c2f7363726970743e3c2f626f64793e3c2f688152633a36b61f60e11b602082015260240103601f19810182526127189082610dc1565b61272190614ddc565b61158a90614ce3565b90919381600061275761076f61076f6127428a6148ac565b905460039190911b1c6001600160a01b031690565b60405163048dd91f60e11b815292839182905afa8015610c305761278d9261278792600092612794575b50614ca2565b94613d71565b91906121b7565b6127b091923d8091833e6127a88183610dc1565b810190614c7d565b9038612781565b6127c96127d791969394959296615ecd565b828082518301019101614a3e565b916000935b83518510156128885761283790600061280c61076f61076f6127fe8a8a613d96565b51516001600160a01b031690565b856128178989613d96565b510151604051631c10ed5560e31b81529485929183918291828f01610499565b03915afa908115610c305761285b6127879261286194600091612867575b50615d17565b90614c14565b936127dc565b612882913d8091833e61287a8183610dc1565b810190614b12565b38612855565b92509490939250386121af565b346103a95760803660031901126103a9576004356128b2816105bd565b6024356128be816105bd565b606435916001600160401b0383116103a9576128e161044f933690600401611add565b9160443591615820565b346103a95760203660031901126103a957600435600052609e602052602060018060a01b0360406000205416604051908152f35b346103a9576020806003193601126103a95760043590612951600092808452609d83526113d1604085205415156149be565b604051918360a3549061296382612f24565b916001908181169081156129c9575060011461298c575b610505866104f981610ec88b8a614bfd565b909192955060a382528582205b8383106129b65750505082019092019181610ec88261050561297a565b8054868401880152918601918101612999565b60ff19168588015250505080151502830101925081610ec88261050561297a565b346103a9576129f836610865565b90612a0e60018060a01b03606a54163314613a10565b6001600160401b038211610d8657600160401b8211610d865760a4548260a455808310612a9e575b5060a460009081529190600080516020615f2b8339815191526020845b848110612a8257857f69a14dc09c71917f03857a09574ce712b7e73c083e26968c14ca72da507fa14e8180a180f35b600190828535612a91816105bd565b9501948185015501612a53565b60a4600052612ac190600080516020615f2b833981519152908101908401612f5e565b38612a36565b60403660031901126103a957600435612adf816105bd565b602435612b1666ffffffffffffff612b0360ac5466ffffffffffffff9060a01c1690565b16612b0f811515613ef4565b4211613f31565b60ad54612b6d612b326001600160601b038360601c1684613296565b610adc60675493612023610ad3612b498888613aa4565b9263ffffffff612b6260a65463ffffffff9060d81c1690565b9160c01c1690613c3b565b612b78323314613cd2565b612b853460a0540160a055565b60005b828110612b9157005b80610bf9612ba2612bac9385613aa4565b6107813382614735565b612b88565b346103a95760403660031901126103a957602060ff612c0d600435612bd5816105bd565b60243590612be2826105bd565b60018060a01b03166000526069845260406000209060018060a01b0316600052602052604060002090565b54166040519015158152f35b60003660031901126103a95761044f6143d5565b346103a95760003660031901126103a957602066ffffffffffffff60aa5460a01c16604051908152f35b346103a95760203660031901126103a957600435612c74816105bd565b606a546001600160a01b0390612c8d9082163314613a10565b811615612c9d5761044f90615dc9565b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b346103a95760603660031901126103a957600435612d0e816105bd565b60243590612d1b826105bd565b6044356001600160401b0381116103a957612d3a903690600401610e08565b60005b815181101561044f5780610bf9612d57612d6c9385613d96565b51612d65610a2582336158f6565b86866159d2565b612d3d565b346103a95760203660031901126103a957600435612d8e816106bf565b612da360018060a01b03606a54163314613a10565b60675462ffffff821690811115612e43577f291346a9a1a36b98232bf8d9776ead3b0666a0a277b084d36170daab32d1c3c591612df96119cb92612df3610ad360a65463ffffffff9060d81c1690565b116151f9565b612e2d612e086117cb83615230565b60a6805463ffffffff60d81b191660d89290921b63ffffffff60d81b16919091179055565b60405162ffffff90911681529081906020820190565b60405162461bcd60e51b8152602060048201526007602482015266546f6f206c6f7760c81b6044820152606490fd5b15612e7957565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b903590601e19813603018212156103a957018035906001600160401b0382116103a9576020019181360383136103a957565b60405190612f1482610da6565b60008252565b356104aa816105bd565b90600182811c92168015612f54575b6020831014612f3e57565b634e487b7160e01b600052602260045260246000fd5b91607f1691612f33565b818110612f69575050565b60008155600101612f5e565b90601f8211612f82575050565b610def9160656000526020600020906020601f840160051c83019310612fb0575b601f0160051c0190612f5e565b9091508190612fa3565b90601f8211612fc7575050565b610def9160a36000526020600020906020601f840160051c83019310612fb057601f0160051c0190612f5e565b90601f8211613001575050565b610def9160666000526020600020906020601f840160051c83019310612fb057601f0160051c0190612f5e565b90601f821161303b575050565b610def9160a26000526020600020906020601f840160051c83019310612fb057601f0160051c0190612f5e565b91906001600160401b038111610d865761308c8161308760a254612f24565b61302e565b6000601f82116001146130c6578192936000926130bb575b50508160011b916000199060031b1c19161760a255565b0135905038806130a4565b60a2600052601f198216937faaf4f58de99300cfadc4585755f376d5fa747d5bc561d5bd9d710de1f91bf42d91805b86811061312d5750836001959610613113575b505050811b0160a255565b0135600019600384901b60f8161c19169055388080613108565b909260206001819286860135815501940191016130f5565b91906001600160401b038111610d86576131648161196460a354612f24565b6000601f821160011461319e57819293600092613193575b50508160011b916000199060031b1c19161760a355565b01359050388061317c565b60a3600052601f198216937f60859188cffe297f44dde29f2d2865634621f26215049caeb304ccba566a8b1791805b86811061320557508360019596106131eb575b505050811b0160a355565b0135600019600384901b60f8161c191690553880806131e0565b909260206001819286860135815501940191016131cd565b903590601e19813603018212156103a957018035906001600160401b0382116103a957602001918160051b360383136103a957565b634e487b7160e01b600052601160045260246000fd5b600281901b91906001600160fe1b038116036107a257565b906007820291808304600714901517156107a257565b818102929181159184041417156107a257565b6001600160401b038211610d8657600160401b8211610d865760a4548260a45580831061330b575b5060a46000526020806000209060005b8481106132ef575050505050565b600190828535956132ff876105bd565b019481850155016132e1565b60a460005261332e90600080516020615f2b833981519152908101908401612f5e565b386132d1565b3566ffffffffffffff811681036103a95790565b63ffffffff8116036103a957565b356104aa81613348565b356001600160601b03811681036103a95790565b356104aa816106bf565b613851610360610def9261339b6133958280612ed5565b90613068565b6133b16133ab6020830183612ed5565b90613145565b6133c76133c1604083018361321d565b906132a9565b606081013560a5556134006133de60808301612f1a565b60a680546001600160a01b0319166001600160a01b0392909216919091179055565b61343a61340f60a08301613334565b60a6805466ffffffffffffff60a01b191660a09290921b66ffffffffffffff60a01b16919091179055565b613449612e0860c08301613356565b61347a61345860e08301612f1a565b60a780546001600160a01b0319166001600160a01b0392909216919091179055565b6134af61348a6101008301613360565b60a780546001600160a01b031660a09290921b6001600160a01b031916919091179055565b6134e16134bf6101208301612f1a565b60a880546001600160a01b0319166001600160a01b0392909216919091179055565b6135166134f16101408301613360565b60a880546001600160a01b031660a09290921b6001600160a01b031916919091179055565b6135486135266101608301612f1a565b60a980546001600160a01b0319166001600160a01b0392909216919091179055565b61357b6135586101808301613374565b60a9805462ffffff60a01b191660a09290921b62ffffff60a01b16919091179055565b6135ae61358b6101a08301613374565b60a9805462ffffff60b81b191660b89290921b62ffffff60b81b16919091179055565b6135e16135be6101c08301613374565b60a9805462ffffff60d01b191660d09290921b62ffffff60d01b16919091179055565b6136166135f16101e08301613374565b60a980546001600160e81b031660e89290921b6001600160e81b031916919091179055565b6136486136266102008301612f1a565b60aa80546001600160a01b0319166001600160a01b0392909216919091179055565b6136836136586102208301613334565b60aa805466ffffffffffffff60a01b191660a09290921b66ffffffffffffff60a01b16919091179055565b6136b86136936102408301613356565b60aa805463ffffffff60d81b191660d89290921b63ffffffff60d81b16919091179055565b6136c86109076102608301612f1a565b6137036136d86102808301613334565b60ab805466ffffffffffffff60a01b191660a09290921b66ffffffffffffff60a01b16919091179055565b6137386137136102a08301613356565b60ab805463ffffffff60d81b191660d89290921b63ffffffff60d81b16919091179055565b61376a6137486102c08301612f1a565b60ac80546001600160a01b0319166001600160a01b0392909216919091179055565b6137a561377a6102e08301613334565b60ac805466ffffffffffffff60a01b191660a09290921b66ffffffffffffff60a01b16919091179055565b6137da6137b56103008301613356565b60ac805463ffffffff60d81b191660d89290921b63ffffffff60d81b16919091179055565b6138066137ea6103208301613360565b6001600160601b03166001600160601b031960ad54161760ad55565b61384b6138166103408301613360565b60ad80546bffffffffffffffffffffffff60601b191660609290921b6bffffffffffffffffffffffff60601b16919091179055565b01613356565b60ad805463ffffffff60c01b191660c09290921b63ffffffff60c01b16919091179055565b61388a6138838280612ed5565b3691611aa6565b6040519061389782610d6b565b600782526020660e13905410549560ca1b818401526138c660ff60005460081c166138c181615435565b615435565b8151916001600160401b038311610d86576138eb836138e6606554612f24565b612f75565b81601f84116001146139805750918061394395949261392694600092613975575b50508160011b916000199060031b1c191617606555615495565b61393e61393961076f6101608401612f1a565b615db0565b61337e565b6001600160a01b0381166139545750565b60ab80546001600160a01b0319166001600160a01b03909216919091179055565b01519050388061390c565b60656000529190601f1984167f8ff97419363ffd7000167f130ef7168fbea05faf9251824ca5043f113cc6a7c7936000905b8282106139f857505092600192859261392696613943999896106139df575b505050811b01606555615495565b015160001960f88460031b161c191690553880806139d1565b806001869782949787015181550196019401906139b2565b15613a1757565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b90600182018092116107a257565b90600282018092116107a257565b907f060606060606060606060606060606060606060606060606060606060606060682018092116107a257565b919082018092116107a257565b15613ab857565b60405162461bcd60e51b815260206004820152600a602482015269135a5b9d1959081bdd5d60b21b6044820152606490fd5b15613af157565b60405162461bcd60e51b815260206004820152601460248201527309ad2dce840dac2f040ccdeeae440e0cae440e8f60631b6044820152606490fd5b15613b3457565b60405162461bcd60e51b815260206004820152601b60248201527f416c6c6f77206c697374206d696e74206e6f74207374617274656400000000006044820152606490fd5b15613b8057565b60405162461bcd60e51b8152602060048201526015602482015274105b1b1bddc81b1a5cdd081b5a5b9d08195b991959605a1b6044820152606490fd5b15613bc457565b60405162461bcd60e51b8152602060048201526011602482015270139bdd081bdb88185b1b1bddc81b1a5cdd607a1b6044820152606490fd5b15613c0457565b60405162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e4818db185a5b5959608a1b6044820152606490fd5b63ffffffff91821690821603919082116107a257565b15613c5857565b60405162461bcd60e51b815260206004820152600d60248201526c4e6f7420617661696c61626c6560981b6044820152606490fd5b15613c9457565b60405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a5908199d5b991cc81c1c9bdd9a59195960521b6044820152606490fd5b15613cd957565b60405162461bcd60e51b81526020600482015260136024820152724e6f20636f6e7472616374206d696e74696e6760681b6044820152606490fd5b929091906000915b8451831015613d6957613d2f8386613d96565b5190600082821015613d575750600052602052613d5160406000205b92613d71565b91613d1c565b604091613d5193825260205220613d4b565b915092501490565b60001981146107a25760010190565b634e487b7160e01b600052603260045260246000fd5b8051821015613daa5760209160051b010190565b613d80565b15613db657565b60405162461bcd60e51b815260206004820152601a60248201527f4d696e742070617373206d696e74206e6f7420737461727465640000000000006044820152606490fd5b15613e0257565b60405162461bcd60e51b8152602060048201526014602482015273135a5b9d081c185cdcc81b5a5b9d08195b99195960621b6044820152606490fd5b15613e4557565b60405162461bcd60e51b81526020600482015260116024820152704d696e74206174206c65617374206f6e6560781b6044820152606490fd5b9190811015613daa5760051b0190565b908160209103126103a957516104aa816105bd565b6040513d6000823e3d90fd5b15613eb657565b60405162461bcd60e51b8152602060048201526016602482015275135a5b9d081c185cdcc8185b1c9958591e481d5cd95960521b6044820152606490fd5b15613efb57565b60405162461bcd60e51b815260206004820152600e60248201526d139bc81c1d589b1a58c81b5a5b9d60921b6044820152606490fd5b15613f3857565b60405162461bcd60e51b8152602060048201526017602482015276141d589b1a58c81b5a5b9d081b9bdd081cdd185c9d1959604a1b6044820152606490fd5b15613f7e57565b60405162461bcd60e51b8152602060048201526019602482015278109a59191a5b99c81c1a185cd9481b9bdd081cdd185c9d1959603a1b6044820152606490fd5b15613fc657565b60405162461bcd60e51b81526020600482015260156024820152744e6f20636f6e74726163742072657665616c696e6760581b6044820152606490fd5b1561400a57565b60405162461bcd60e51b815260206004820152601360248201527241756374696f6e20696e2070726f677265737360681b6044820152606490fd5b1561404c57565b60405162461bcd60e51b815260206004820152601060248201526f105b1c9958591e481c995d99585b195960821b6044820152606490fd5b60ff66ffffffffffffff806140a560ac5466ffffffffffffff9060a01c1690565b168015614203574211806141c0575b6140bd90613f77565b6140c8323314613fbf565b6140d860b1549182164211614003565b60381c1615806141b5575b6141a8575b6141816067546140fa610ac282613a5b565b61410660b05415614045565b6141103382614735565b61412482600052609d602052604060002090565b5561415c3361413d83600052609e602052604060002090565b80546001600160a01b0319166001600160a01b03909216919091179055565b60b1805467ffffffffffffffff1916905561417c600060ae55600060af55565b60b055565b7fabfa50b1969c21cf8a6ef98cc34a97b3c5ce9fe16e1268ffaa57c272faccbcab600080a1565b6141b0614617565b6140e8565b5060af5415156140e3565b506140bd6141cf606754613a5b565b6141fa610ad36141e860a65463ffffffff9060d81c1690565b60ad5460c01c63ffffffff1690613c3b565b111590506140b4565b50614227614220610a5460a65466ffffffffffffff9060a01c1690565b4211613f77565b6140bd565b1561423357565b60405162461bcd60e51b815260206004820152601260248201527114995d99585b081c1a5958d948199a5c9cdd60721b6044820152606490fd5b1561427457565b60405162461bcd60e51b815260206004820152601d60248201527f426964206973206c6f776572207468616e206d696e696d756d206269640000006044820152606490fd5b156142c057565b60405162461bcd60e51b81526020600482015260136024820152724e6f20636f6e74726163742062696464696e6760681b6044820152606490fd5b1561430257565b60405162461bcd60e51b815260206004820152602960248201527f426964206d757374206265203e2035252067726561746572207468616e2063756044820152681c9c995b9d08189a5960ba1b6064820152608490fd5b6040519061436682610d6b565b60ae546001600160a01b0316825260af546020830152565b1561438557565b60405162461bcd60e51b815260206004820152600d60248201526c105d58dd1a5bdb88195b991959609a1b6044820152606490fd5b91909166ffffffffffffff808094169116019182116107a257565b6143f66143ee606754600052609d602052604060002090565b54151561422c565b614410614408610aa360a85460a01c90565b34101561426d565b61441b3233146142b9565b61443561442e60af546014810490613aa4565b34116142fb565b61443d614359565b61446d614448610de2565b3380825234602090920182905260ae80546001600160a01b031916909117905560af55565b66ffffffffffffff8061448860b15466ffffffffffffff1690565b161561459357600080809381936144a760b15466ffffffffffffff1690565b9081166144b581421061437e565b6144d46144ce610ad360ac5463ffffffff9060d81c1690565b42613aa4565b1161454e575b5080516020906144f2906001600160a01b031661076f565b91015190828215614545575bf115610c30575b6040805160ae546001600160a01b0316815260af5460208201527ffa040d55a6992a6143e6ea8c968e9530213b85d9a399be45045c7f5d5065bd579190a1565b506108fc6144fe565b61457161458d9161456b610ad360ab5463ffffffff9060d81c1690565b906143ba565b66ffffffffffffff1666ffffffffffffff1960b154161760b155565b386144da565b6145c39150614571906145b2610ad360aa5463ffffffff9060d81c1690565b429091160166ffffffffffffff1690565b614505565b156145cf57565b60405162461bcd60e51b8152602060048201526013602482015272105d58dd1a5bdb881b9bdd081cdd185c9d1959606a1b6044820152606490fd5b919082039182116107a257565b61463c66ffffffffffffff61463460b15466ffffffffffffff1690565b1615156145c8565b60ae546001600160a01b031661466461076f6112aa60b054600052609e602052604060002090565b6001600160a01b03918216036146d757600080808060af5461469d6117ec6117e46117dd6117d36117cb60a95462ffffff9060a01c1690565b60ae546146b2906001600160a01b031661076f565b8282156146ce575bf115610c3057610def90611837600060b055565b506108fc6146ba565b610def906146ec6117ec60af5460a054613aa4565b61182d565b156146f857565b60405162461bcd60e51b8152602060048201526015602482015274105d58dd1a5bdb881b9bdd0818dbdb98db1d591959605a1b6044820152606490fd5b9060405190602082019283526001600160601b03199060601b1660408201526000194301406054820152600119430140607482015260031943014060948201524460b48201524160601b60d482015260c8815261010081018181106001600160401b03821117610d865760405251902090565b156147af57565b60405162461bcd60e51b815260206004820152600b60248201526a139bdd08185b1b1bddd95960aa1b6044820152606490fd5b156147e957565b60405162461bcd60e51b815260206004820152600f60248201526e42616c616e6365206973207a65726f60881b6044820152606490fd5b9061482a8261557a565b80156148915761483981610df1565b906148476040519283610dc1565b808252601f1961485682610df1565b0136602084013760005b81811061486e575090925050565b8061487c61488c928761538c565b6148868286613d96565b52613d71565b614860565b5090506040516148a081610da6565b60008152600036813790565b60a454811015613daa5760a460005260206000200190600090565b606754811015613daa57606760005260206000200190600090565b90916000906067908154925b81811061490057505050505050600190565b61490b818388613e7e565b3584811015613daa5760008481526020902001546001600160a01b03908116908616036149405761493b90613d71565b6148ee565b505050505050600090565b606754600160401b811015610d86578161496e82600161498d94016067556148c7565b90919082549060031b9160018060a01b03809116831b921b1916179055565b6001600160a01b031660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4565b156149c557565b60405162461bcd60e51b815260206004820152600f60248201526e151bdad95b881b9bdd08199bdd5b99608a1b6044820152606490fd5b81601f820112156103a9578051614a1281611a8b565b92614a206040519485610dc1565b818452602082840101116103a9576104aa9160208085019101610451565b9060209081838203126103a95782516001600160401b03938482116103a957019080601f830112156103a9578151614a7581610df1565b94604090614a8582519788610dc1565b828752858088019360051b860101948486116103a957868101935b868510614ab257505050505050505090565b84518381116103a95782019084601f1983890301126103a957845190614ad782610d6b565b89830151614ae4816105bd565b825285830151918583116103a957614b03898c809695819601016149fc565b83820152815201940193614aa0565b602080828403126103a95781516001600160401b03928382116103a957019260409283858303126103a957835194614b4986610d6b565b80518652838101519182116103a9570181601f820112156103a957805191614b7083610df1565b94614b7d81519687610dc1565b83865284860191856060809602850101938185116103a9578601925b848410614bac5750505050505082015290565b85848303126103a9578686918451614bc381610d8b565b8651614bce816105bd565b815282870151614bdd81613348565b8382015285870151614bee81613348565b86820152815201930192614b99565b90614c1060209282815194859201610451565b0190565b6030610def919392936040519481614c36879351809260208087019101610451565b82016c6177616974206c73323536282760981b6020820152614c62825180936020602d85019101610451565b016227293b60e81b602d820152036010810185520183610dc1565b906020828203126103a95781516001600160401b0381116103a9576104aa92016149fc565b6020610def919392936040519481614cc38793518092868087019101610451565b8201614cd782518093868085019101610451565b01038085520183610dc1565b90610def603660405180947519185d184e9d195e1d0bda1d1b5b0ed8985cd94d8d0b60521b6020830152614d208151809260208686019101610451565b8101036016810185520183610dc1565b60405190614d3d82610d8b565b604082527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040837f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201520152565b60405190614d9c82610d8b565b602a82526040366020840137565b90614db482611a8b565b614dc16040519182610dc1565b8281528092614dd2601f1991611a8b565b0190602036910137565b805115614eae57614deb614d30565b614e0f614e0a614e05614dfe8551613a69565b6003900490565b613268565b614daa565b9160208301918182518301915b828210614e5c57505050600390510680600114614e4957600214614e3e575090565b603d90600019015390565b50603d9081600019820153600119015390565b9091936004906003809401938451600190603f9082828260121c16880101518553828282600c1c16880101518386015382828260061c1688010151600286015316850101519082015301939190614e1c565b506104aa612f07565b6000908072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b80821015614fe7575b506d04ee2d6d415b85acef810000000080831015614fd8575b50662386f26fc1000080831015614fc9575b506305f5e10080831015614fba575b5061271080831015614fab575b506064821015614f9b575b600a80921015614f91575b600190816021614f49828701614daa565b95860101905b614f5b575b5050505090565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a835304918215614f8c57919082614f4f565b614f54565b9160010191614f38565b9190606460029104910191614f2d565b60049193920491019138614f22565b60089193920491019138614f15565b60109193920491019138614f06565b60209193920491019138614ef4565b604093508104915038614edb565b6150166001600160801b031961500c83821661504f565b9260801b1661504f565b6040519161060f60f31b60208401526022830152604282015260428152608081018181106001600160401b03821117610d865760405290565b8060401c9063ffffffff60401b821663ffffffff60c01b82161760201c9163ffffffff60601b169063ffffffff60e01b1617178060101c907bff00000000000000ff00000000000000ff00000000000000ff0000007aff00000000000000ff00000000000000ff00000000000000ff000083167eff00000000000000ff00000000000000ff00000000000000ff00000000000083161760081c92169078ff00000000000000ff00000000000000ff00000000000000ff60381b1617177f0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f007e0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f8260081c169160041c16177f30303030303030303030303030303030303030303030303030303030303030308181018091116107a2576151c17f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f6151bb6151b56104aa95613a77565b60041c90565b16613280565b90613aa4565b908060209392818452848401376000828201840152601f01601f1916010190565b9160206104aa9381815201916151c7565b1561520057565b60405162461bcd60e51b81526020600482015260086024820152670a8dede40d0d2ced60c31b6044820152606490fd5b90600162ffffff809316019182116107a257565b600b60fa1b815260010190565b908151811015613daa570160200190565b80156107a2576000190190565b1561527657565b606460405162461bcd60e51b815260206004820152602060248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152fd5b6152c2614d8f565b90815115613daa57603060208301538151600190811015613daa5790607860218401536029915b8083116152fc57506104aa91501561526f565b90600f8116906010821015613daa57615339916f181899199a1a9b1b9c1cb0b131b232b360811b901a61532f8587615251565b5360041c92615262565b91906152e9565b60809060208152602b60208201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560408201526a74206f6620626f756e647360a81b60608201520190565b906153968261557a565b81101561541c576000908192606754935b8481106153cb5760405162461bcd60e51b8152806153c760048201615340565b0390fd5b6153da61076f612742836148c7565b6001600160a01b038316146153f8575b6153f390613d71565b6153a7565b9282810361540857505050905090565b6154146153f391613d71565b9390506153ea565b60405162461bcd60e51b8152806153c760048201615340565b1561543c57565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b9081516001600160401b038111610d86576154ba816154b5606654612f24565b612ff4565b602080601f83116001146154f657508192936000926154eb575b50508160011b916000199060031b1c191617606655565b0151905038806154d4565b6066600052601f198316949091907f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e94354926000905b878210615562575050836001959610615549575b505050811b01606655565b015160001960f88460031b161c1916905538808061553e565b8060018596829496860151815501950193019061552a565b6001600160a01b031680156155d757606754600091825b82811061559e5750505090565b6155ad61076f612742836148c7565b82146155c2575b6155bd90613d71565b615591565b926155cf6155bd91613d71565b9390506155b4565b60405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608490fd5b606754811015613daa5760676000527f9787eeb91fe3101235e4a76063c7023ecb40f923f97916639c598592fa30d6ae01546001600160a01b031680156156735790565b60405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608490fd5b156156d157565b60405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776044820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b6064820152608490fd5b615740816158ab565b15615760576000908152606860205260409020546001600160a01b031690565b60405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608490fd5b156157c157565b60405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6044820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b6064820152608490fd5b90615844939291615834610a2584336158f6565b61583f8383836159d2565b615c0d565b1561584b57565b60405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608490fd5b606754811090816158ba575090565b9015613daa5760676000527f9787eeb91fe3101235e4a76063c7023ecb40f923f97916639c598592fa30d6ae01546001600160a01b0316151590565b6158ff826158ab565b156159785761590d8261562f565b6001600160a01b038281168282168114949091908515615960575b505050821561593657505090565b6001600160a01b0316600090815260696020526040902060ff925061595b919061064c565b541690565b61596d9192939550615737565b161491388080615928565b60405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608490fd5b6159db8361562f565b6001600160a01b0391821691908116829003615a88578216918215615a3757615a1090615a0785615adf565b61496e856148c7565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4565b60405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b60405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608490fd5b600081815260686020526040812080546001600160a01b03191690556001600160a01b03615b0c8361562f565b167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258280a4565b600082815260686020526040902080546001600160a01b0319166001600160a01b0383161790556001600160a01b0380615b6c8461562f565b169116907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a4565b908160209103126103a957516104aa81610397565b6001600160a01b0391821681529116602082015260408101919091526080606082018190526104aa92910190610474565b3d15615c08573d90615bee82611a8b565b91615bfc6040519384610dc1565b82523d6000602084013e565b606090565b92909190823b15615d0e57615c40926020926000604051809681958294630a85bd0160e11b9a8b85523360048601615bac565b03926001600160a01b03165af160009181615cde575b50615cd057615c63615bdd565b80519081615ccb5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608490fd5b602001fd5b6001600160e01b0319161490565b615d0091925060203d8111615d07575b615cf88183610dc1565b810190615b97565b9038615c56565b503d615cee565b50505050600190565b90602080920151918251928190604092835195600091825b828410615d4d575050505050601f8019918281018652011683019052565b90919293969594828560051b8901015180518785830151920151813b808211615d92575082849392600195938e930394859301903c0194019291909693949596615d2f565b9260849386936386d14d8960e01b8552600452602452604452606452fd5b610def90615dc960ff60005460081c166138c181615435565b606a80546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b615e94615ea4602e604051615e4f602182602081019760008952615e3f8151809260208686019101610451565b8101036001810184520182610dc1565b8051946040519485926020840197606360f81b895263ffffffff60e01b9060e01b1660218501526880600e6000396000f360b81b602585015251809285850190610451565b810103600e810184520182610dc1565b51906000f0906001600160a01b03821615615ebb57565b60405163046a55db60e11b8152600490fd5b90813b8015615f145780600111615f14576000190160011980821015615f0d57505b600160405193601f19603f840116850160405282855260208501903c565b9050615eef565b509050604051615f2381610da6565b600081529056fee434dc35da084cf8d7e8186688ea2dacb53db7003d427af3abf351bd9d0a4e8da2646970667358221220590f6538a61208647c61924cd45e0da49d6570caaf26118f078b9db4ea8fb60664736f6c63430008130033
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c806301ffc9a714610392578063025ea63d1461038d57806306fdde0314610388578063081812fc14610383578063095ea7b31461037e5780630eaffa031461037957806318160ddd146103745780631cd500a51461036f5780631f1a7d941461036a5780631ffa01c21461036557806321827eff1461036057806323b872dd1461035b57806325161d11146103565780632a55205a146103515780632f745c591461034c578063322736ba1461034757806334e333951461034257806334ecc48f1461033d578063363e86fe146103385780633ccfd60b1461033357806342842e0e1461032e57806342f74cd714610329578063438b63001461032457806346fca9aa1461031f5780634c0f38c21461031a5780634d44660c146103155780634e43663f146103105780634e69d5601461030b5780634e71d92d146103065780634f6ccce71461030157806355f804b3146102fc5780635a4fee30146102f7578063621a1f74146102c55780636352211e146102f257806370a08231146102ed578063715018a6146102e857806378aa7d38146102e35780638da5cb5b146102de57806395d89b41146102d95780639bb22b40146102d45780639df742d7146102cf578063a22cb465146102ca578063a3864397146102c5578063a7a50365146102c0578063b79bebaf146102bb578063b88d4fde146102b6578063c1b8ce2e146102b1578063c87b56dd146102ac578063ce67764c146102a7578063ce6df2b9146102a2578063e985e9c51461029d578063ecfc7ecc14610298578063ed6f452014610293578063f2fde38b1461028e578063f3993d11146102895763fe0d8aac1461028457600080fd5b612d71565b612cf1565b612c57565b612c2d565b612c19565b612bb1565b612ac7565b6129ea565b61291f565b6128eb565b612895565b612161565b612140565b611b86565b612054565b611e61565b611e3a565b611d96565b611d6d565b611c58565b611bf7565b611bd0565b611bb2565b611af8565b6118f6565b611873565b611728565b611272565b611248565b6111f6565b6111c1565b61119a565b611131565b611108565b6110e0565b610f66565b610f3c565b610f15565b610e66565b610cac565b610c79565b610c35565b610a2f565b610a06565b610893565b610819565b6107ef565b6107c5565b6107a7565b6106cc565b6105ce565b61058d565b6104ad565b610436565b6103ae565b6001600160e01b03198116036103a957565b600080fd5b346103a95760203660031901126103a95760206004356103cd81610397565b63ffffffff60e01b1663780e9d6360e01b81149081156103f3575b506040519015158152f35b6380ac58cd60e01b811491508115610425575b8115610414575b50386103e8565b6301ffc9a760e01b1490503861040d565b635b5e139f60e01b81149150610406565b346103a95760003660031901126103a95761044f614084565b005b60005b8381106104645750506000910152565b8181015183820152602001610454565b9060209161048d81518092818552858086019101610451565b601f01601f1916010190565b9060206104aa928181520190610474565b90565b346103a95760008060031936011261058a57604051816065546104cf81612f24565b808452906001908181169081156105625750600114610509575b610505846104f981880382610dc1565b60405191829182610499565b0390f35b60658352602094507f8ff97419363ffd7000167f130ef7168fbea05faf9251824ca5043f113cc6a7c75b82841061054f5750505081610505936104f992820101936104e9565b8054858501870152928501928101610533565b61050596506104f99450602092508593915060ff191682840152151560051b820101936104e9565b80fd5b346103a95760203660031901126103a95760206105ab600435615737565b6040516001600160a01b039091168152f35b6001600160a01b038116036103a957565b346103a95760403660031901126103a9576004356105eb816105bd565b6024356105f78161562f565b916001600160a01b0380841690821681146106705761044f93610624913314908115610629575b506156ca565b615b33565b6001600160a01b0316600090815260696020526040902061066a91506106639033905b9060018060a01b0316600052602052604060002090565b5460ff1690565b3861061e565b60405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608490fd5b62ffffff8116036103a957565b346103a95760403660031901126103a9576004356106e9816106bf565b602435906106f6826105bd565b61070b60018060a01b03606a54163314613a10565b62ffffff6067549116908181018082116107a25760a654610737919060d81c63ffffffff165b11613ab1565b61074360058310613aea565b60005b82811061074f57005b8061079c600192840161078161077b61076f60a95460018060a01b031690565b6001600160a01b031690565b82614735565b61079582600052609d602052604060002090565b558661494b565b01610746565b613252565b346103a95760003660031901126103a9576020606754604051908152f35b346103a95760003660031901126103a957602066ffffffffffffff60a65460a01c16604051908152f35b346103a95760003660031901126103a957602066ffffffffffffff60ab5460a01c16604051908152f35b60003660031901126103a95761082d614084565b61044f6143d5565b9181601f840112156103a9578235916001600160401b0383116103a9576020808501948460051b0101116103a957565b60206003198201126103a957600435906001600160401b0382116103a95761088f91600401610835565b9091565b346103a9576108a136610865565b9060018060a01b036108b881606a54163314613a10565b6040928351928484019082602092838088015252606085019560608460051b8701019682956000935b868510610950576109296109078a610902818e03601f198101835282610dc1565b615e12565b60ab80546001600160a01b0319166001600160a01b0392909216919091179055565b7fd6a2280fab4cc808ebb209359e38f6c624e9567ae7b4bb53569ce27639c26b79600080a1005b9091929394959698605f198982030184528935603e19833603018112156103a957820183813561097f816105bd565b16825287810135601e19823603018112156103a9570187810190356001600160401b0381116103a95780360382136103a9576109c88992839289868186600199015201916151c7565b9b0194019501939296959491906108e1565b60609060031901126103a9576004356109f2816105bd565b906024356109ff816105bd565b9060443590565b346103a95761044f610a17366109da565b91610a2a610a2584336158f6565b6157ba565b6159d2565b610a3836610865565b610a67610a60610a5460aa5466ffffffffffffff9060a01c1690565b66ffffffffffffff1690565b4211613daf565b610a8a610a83610a5460ab5466ffffffffffffff9060a01c1690565b4210613dfb565b60675491610afb610ab5610aaf610aa360a75460a01c90565b6001600160601b031690565b84613296565b610adc610ac28587613aa4565b60a6546107319060d81c63ffffffff165b63ffffffff1690565b610ae7841515613e3e565b610af360058510613aea565b341015613c8d565b610b06323314613cd2565b60ac54610b1b906001600160a01b031661076f565b90610b293460a0540160a055565b6001600160a01b039091169060005b838110610b4157005b610b4c818584613e7e565b6040516331a9108f60e11b8152903560048201529060208083602481885afa8015610c3057610bfe93610bf992600092610c03575b5050610b8d8389613aa4565b90610bb9610bb4610bb0610ba2878c8b613e7e565b356001901b609f5416151590565b1590565b613eaf565b610bd5610bc7858a89613e7e565b356001901b609f5417609f55565b610bdf3383614735565b610bf383600052609d602052604060002090565b5561494b565b613d71565b610b38565b610c229250803d10610c29575b610c1a8183610dc1565b810190613e8e565b3880610b81565b503d610c10565b613ea3565b346103a95760403660031901126103a957604060018060a01b0360a85416612710610c6c62ffffff60a95460b81c16602435613296565b0482519182526020820152f35b346103a95760403660031901126103a9576020610ca4600435610c9b816105bd565b6024359061538c565b604051908152f35b346103a95760008060031936011261058a57604051809160a454908183526020809301809260a4835284832090835b818110610d385750505084610cf1910385610dc1565b60405193838594850191818652518092526040850193925b828110610d1857505050500390f35b83516001600160a01b031685528695509381019392810192600101610d09565b82546001600160a01b031684529286019260019283019201610cdb565b634e487b7160e01b600052604160045260246000fd5b604081019081106001600160401b03821117610d8657604052565b610d55565b606081019081106001600160401b03821117610d8657604052565b602081019081106001600160401b03821117610d8657604052565b90601f801991011681019081106001600160401b03821117610d8657604052565b60405190610def82610d6b565b565b6001600160401b038111610d865760051b60200190565b81601f820112156103a957803591610e1f83610df1565b92610e2d6040519485610dc1565b808452602092838086019260051b8201019283116103a9578301905b828210610e57575050505090565b81358152908301908301610e49565b346103a95760403660031901126103a957600435610e83816105bd565b6024356001600160401b0381116103a957610ea5610ee3913690600401610e08565b604051606084901b6001600160601b0319166020820190815290610ed681603481015b03601f198101835282610dc1565b5190209060a55490613d14565b6001600160a01b03919091166000908152609c6020908152604091829020548251931515845260ff1615159083015290f35b346103a95760203660031901126103a957602060016004351b609f54161515604051908152f35b346103a95760003660031901126103a95760206001600160601b0360ad5460601c16604051908152f35b346103a95760008060031936011261058a5760aa54610f8d906001600160a01b031661076f565b331480156110c3575b80156110a0575b610fa6906147a8565b610fdd60a054610fb78115156147e2565b82808080610ffe60a95495610ff9610ff1610fe5610fdd62ffffff8b60d01c1685613296565b612710900490565b998a9960e81c84613296565b97889261460a565b61460a565b95611009600060a055565b60aa5461101e906001600160a01b031661076f565b828215611097575bf115610c305760a7548391829182918291611049906001600160a01b031661076f565b82821561108e575bf115610c305760a9548291829182918291611074906001600160a01b031661076f565b828215611085575bf115610c305780f35b506108fc61107c565b506108fc611051565b506108fc611026565b5060a754610fa6906110ba906001600160a01b031661076f565b33149050610f9d565b5060a9546110d9906001600160a01b031661076f565b3314610f96565b346103a95761044f6110f1366109da565b90604051926110ff84610da6565b60008452615820565b346103a95760003660031901126103a95760a6546040516001600160a01b039091168152602090f35b346103a9576020806003193601126103a957611157600435611152816105bd565b614820565b906040519181839283018184528251809152816040850193019160005b82811061118357505050500390f35b835185528695509381019392810192600101611174565b346103a95760003660031901126103a957602063ffffffff60ad5460c01c16604051908152f35b346103a95760003660031901126103a95763ffffffff6000198160a65460d81c16018181116107a25760209160405191168152f35b346103a95760403660031901126103a957600435611213816105bd565b6024356001600160401b0381116103a95760209161123861123e923690600401610835565b916148e2565b6040519015158152f35b346103a95760003660031901126103a957602066ffffffffffffff60ac5460a01c16604051908152f35b346103a95760008060031936011261058a578081908291838081606754936112bd6112b76112aa87600052609e602052604060002090565b546001600160a01b031690565b95613a5b565b9660a654966112ea610ad36112db60ad5463ffffffff9060c01c1690565b63ffffffff8b60d81c16613c3b565b90611304610a5460aa5466ffffffffffffff9060a01c1690565b421180611708575b156116df57506001925b60ab5461132e9060a01c66ffffffffffffff16610a54565b4211806116aa575b1561166457506001985b66ffffffffffffff8061135f60ac5466ffffffffffffff9060a01c1690565b169384159485158091819261165a575b5080611651575b156116305750506001995b84611621575b50508215611616575b50506115a7575b6113af6113a96113a96113b593614eb7565b98614eb7565b95614eb7565b906113dc6113d66113d1610a5460b15466ffffffffffffff1690565b614eb7565b93614eb7565b936001600160a01b03906113f19082166152ba565b95169050806115985750611403612f07565b945b604051607b60f81b602082015297889760218901701136b4b73a2830b9b9a9ba30ba3ab9911d60791b815260110161143c91614bfd565b61144590615244565b711130b63637bba634b9ba29ba30ba3ab9911d60711b815260120161146991614bfd565b61147290615244565b6f1130bab1ba34b7b729ba30ba3ab9911d60811b815260100161149491614bfd565b61149d90615244565b6e11383ab13634b1a9ba30ba3ab9911d60891b8152600f016114be91614bfd565b6114c790615244565b701130bab1ba34b7b722b7322a34b6b2911d60791b81526011016114ea91614bfd565b6114f390615244565b721131bab93932b73a2134b220b6b7bab73a111d60691b815260130161151891614bfd565b61152190615244565b701131bab93932b73a2134b23232b9111d1160791b815260110161154491614bfd565b6d1116113932bb32b0b632b9111d1160911b8152600e0161156491614bfd565b601160f91b8152600101607d60f81b815260010103601f198101825261158a9082610dc1565b604051610505819282610499565b6115a1906152ba565b94611405565b92909196506001966115c4610a5460b15466ffffffffffffff1690565b4210156115fd57505060af54906113b56113af6113a96113a96115f161076f60ae5460018060a01b031690565b965b9350505050611397565b91909296506113b56113af6113a96113a960029a6115f3565b101590503880611390565b60a01c16421192503880611387565b909a9080611647575b156113815760029a50611381565b5083831015611639565b50848410611376565b905042113861136f565b9866ffffffffffffff8960a01c1642101580611689575b156113405760029950611340565b5060ac546116a29060a01c66ffffffffffffff16610a54565b42101561167b565b5066ffffffffffffff8960a01c16421080611336575060ac546116d89060a01c66ffffffffffffff16610a54565b4210611336565b926116f9610a5460ab5466ffffffffffffff9060a01c1690565b42106113165760029350611316565b5060ab546117219060a01c66ffffffffffffff16610a54565b421061130c565b346103a95760008060031936011261058a5761176b60ff60b15461176166ffffffffffffff821661175a8115156145c8565b42116146f1565b60381c1615613bfd565b60ae546001600160a01b031661179361076f6112aa60b054600052609e602052604060002090565b6001600160a01b0391821603611859578180808060af546117f16117ec6117e46117dd6117d36117cb60a95462ffffff9060a01c1690565b62ffffff1690565b6127108604613296565b809461460a565b60a054613aa4565b60a055565b60ae54611806906001600160a01b031661076f565b828215611850575bf115610c305761184d905b60b1805460ff60381b1916600160381b1790555b611837600060b055565b60ae546001600160a01b031660b054911661494b565b80f35b506108fc61180e565b61184d9061186e6117ec60af5460a054613aa4565b611819565b346103a95760203660031901126103a95760043560675481101561189c57602090604051908152f35b60405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608490fd5b346103a9576020806003193601126103a9576001600160401b03906004358281116103a957366023820112156103a95780600401359283116103a957602491368385840101116103a95761195560018060a01b03606a54163314613a10565b6119698461196460a354612f24565b612fba565b600090601f85116001146119dd5750837ff9c7803e94e0d3c02900d8a90893a6d5e90dd04d32a4cfe825520f82bf9f32f694846119cb936000926119d0575b50508160011b906000198360031b1c19161760a3555b60405193849301836151e8565b0390a1005b85010135905084386119a8565b60a360005290601f1985167f60859188cffe297f44dde29f2d2865634621f26215049caeb304ccba566a8b179282905b828210611a715750509185917ff9c7803e94e0d3c02900d8a90893a6d5e90dd04d32a4cfe825520f82bf9f32f6966119cb9410611a55575b5050600181811b0160a3556119be565b8401850135600019600384901b60f8161c191690553880611a45565b8060018596898395978a0101358155019501930190611a0d565b6001600160401b038111610d8657601f01601f191660200190565b929192611ab282611a8b565b91611ac06040519384610dc1565b8294818452818301116103a9578281602093846000960137010152565b9080601f830112156103a9578160206104aa93359101611aa6565b346103a95760803660031901126103a957600435611b15816105bd565b60243590611b22826105bd565b6001600160401b036044358181116103a957611b42903690600401610e08565b906064359081116103a957611b5b903690600401611add565b60005b825181101561044f5780610bf983611b79611b819487613d96565b518888615820565b611b5e565b346103a95760203660031901126103a957600435600052609d6020526020604060002054604051908152f35b346103a95760203660031901126103a95760206105ab60043561562f565b346103a95760203660031901126103a9576020610ca4600435611bf2816105bd565b61557a565b346103a95760008060031936011261058a57606a5481906001600160a01b03811690611c24338314613a10565b6001600160a01b031916606a557f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b346103a9576003196040368201126103a957600435906001600160401b0382116103a9576103809082360301126103a957611cdd602435611c98816105bd565b60005492611cbd60ff8560081c161580958196611d5f575b8115611d3f575b50612e72565b83611cd0600160ff196000541617600055565b611d26575b600401613876565b611ce357005b611cf361ff001960005416600055565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989080602081016119cb565b611d3a61010061ff00196000541617600055565b611cd5565b303b15915081611d51575b5038611cb7565b6001915060ff161438611d4a565b600160ff8216109150611cb0565b346103a95760003660031901126103a957606a546040516001600160a01b039091168152602090f35b346103a95760008060031936011261058a5760405181606654611db881612f24565b808452906001908181169081156105625750600114611de157610505846104f981880382610dc1565b60668352602094507f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e943545b828410611e275750505081610505936104f992820101936104e9565b8054858501870152928501928101611e0b565b346103a95760003660031901126103a95760206001600160601b0360ad5416604051908152f35b60403660031901126103a9576004356001600160401b0381116103a957611e8f61044f913690600401610e08565b602435611e9b816105bd565b611ebe611eb7610a5460ab5466ffffffffffffff9060a01c1690565b4211613b2d565b611f8760a654611f23611f1e66ffffffffffffff95868460a01c164210801561202e575b611eeb90613b79565b60a554604051606088901b6001600160601b0319166020820190815290611f158160348101610ec8565b51902091613d14565b613bbd565b6001600160a01b0383166000908152609c60205260409020611f4e90611f4890610663565b15613bfd565b60675493611f6860ac5466ffffffffffffff9060a01c1690565b16611fef575b63ffffffff611f7c85613a5b565b9160d81c1611613ab1565b611fae611f9c60ad546001600160601b031690565b6001600160601b033491161115613c8d565b611fb9323314613cd2565b6001600160a01b0381166000908152609c60205260409020611fe290805460ff19166001179055565b610bd53460a0540160a055565b612029611ffb85613a5b565b612023610ad361201460ad5463ffffffff9060c01c1690565b63ffffffff8660d81c16613c3b565b11613c51565b611f6e565b50611eeb61204b610a5460ac5466ffffffffffffff9060a01c1690565b42109050611ee2565b346103a95760403660031901126103a957600435612071816105bd565b60243580151581036103a9576001600160a01b038216913383146120ff57816120bc6120cd9233600052606960205260406000209060018060a01b0316600052602052604060002090565b9060ff801983541691151516179055565b604051901515815233907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3190602090a3005b60405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b6044820152606490fd5b346103a95760003660031901126103a957602060a75460a01c604051908152f35b346103a9576020806003193601126103a95760049081359161219861219084600052609d602052604060002090565b5415156149be565b60ab5460609182916001600160a01b0316806127b7575b5060a4546000915b81831061272a575050506121ca84614eb7565b936121df90600052609d602052604060002090565b546121e990614ff5565b6040517f3c68746d6c3e3c686561643e3c7363726970743e6c657420696e7075744461749481019485526d0309ebd93ba37b5b2b724b2139d160951b6020860152948594602e0161223991614bfd565b692c2768617368273a202760b01b8152600a0161225591614bfd565b602760f81b8152600101617d3b60f01b8152600201681e17b9b1b934b83a1f60b91b81526009017f3c6d657461206e616d653d2776696577706f72742720636f6e74656e743d277781527f696474683d6465766963652d77696474682c20696e697469616c2d7363616c6560208201527f3d312c206d6178696d756d2d7363616c653d31273e3c7374796c65207479706560408201527f3d27746578742f637373273e68746d6c7b6865696768743a313030253b77696460608201527f74683a313030253b7d626f64797b6865696768743a313030253b77696474683a60808201527f313030253b6d617267696e3a303b70616464696e673a303b6261636b67726f7560a08201527f6e642d636f6c6f723a233030303030303b7d63616e7661737b646973706c617960c08201527f3a626c6f636b3b6d61782d77696474683a313030253b6d61782d68656967687460e08201527f3a313030253b70616464696e673a303b6d617267696e3a6175746f3b646973706101008201527f6c61793a626c6f636b3b706f736974696f6e3a6162736f6c7574653b746f703a6101208201527f303b626f74746f6d3a303b6c6566743a303b72696768743a303b6f626a6563746101408201527516b334ba1d31b7b73a30b4b71dbe9e17b9ba3cb6329f60511b610160820152610176017f3c2f686561643e3c626f64793e3c7363726970742064656665723e6173796e6381527f2066756e6374696f6e206c733235362865297b6c657420743d6e65772054657860208201527f744465636f6465722c613d77696e646f772e61746f622865292c6e3d612e6c6560408201527f6e6774682c723d6e65772055696e74384172726179286e293b666f722876617260608201527f206f3d303b6f3c6e3b6f2b2b29725b6f5d3d612e63686172436f64654174286f60808201527f293b6c657420643d722e6275666665723b6c657420633d6e657720526561646160a08201527f626c6553747265616d287b73746172742865297b652e656e717565756528642960c08201527f2c652e636c6f736528297d7d292e706970655468726f756768286e657720446560e08201527f636f6d7072657373696f6e53747265616d2827677a69702729292c693d6177616101008201527f6974206e657720526573706f6e73652863292c703d617761697420692e6172726101208201527f617942756666657228292c6c3d617761697420742e6465636f64652870292c736101408201527f3d646f63756d656e742e637265617465456c656d656e742827736372697074276101608201527f293b732e747970653d27746578742f6a617661736372697074272c732e6170706101808201527f656e644368696c6428646f63756d656e742e637265617465546578744e6f64656101a08201527f286c29292c646f63756d656e742e626f64792e617070656e644368696c6428736101c08201527f297d3b6173796e632066756e6374696f6e206c6132353628297b0000000000006101e08201526101fa016126b491614bfd565b6c6177616974206c73323536282760981b8152600d016126d391614bfd565b7f27293b7d3b6c6132353628293b3c2f7363726970743e3c2f626f64793e3c2f688152633a36b61f60e11b602082015260240103601f19810182526127189082610dc1565b61272190614ddc565b61158a90614ce3565b90919381600061275761076f61076f6127428a6148ac565b905460039190911b1c6001600160a01b031690565b60405163048dd91f60e11b815292839182905afa8015610c305761278d9261278792600092612794575b50614ca2565b94613d71565b91906121b7565b6127b091923d8091833e6127a88183610dc1565b810190614c7d565b9038612781565b6127c96127d791969394959296615ecd565b828082518301019101614a3e565b916000935b83518510156128885761283790600061280c61076f61076f6127fe8a8a613d96565b51516001600160a01b031690565b856128178989613d96565b510151604051631c10ed5560e31b81529485929183918291828f01610499565b03915afa908115610c305761285b6127879261286194600091612867575b50615d17565b90614c14565b936127dc565b612882913d8091833e61287a8183610dc1565b810190614b12565b38612855565b92509490939250386121af565b346103a95760803660031901126103a9576004356128b2816105bd565b6024356128be816105bd565b606435916001600160401b0383116103a9576128e161044f933690600401611add565b9160443591615820565b346103a95760203660031901126103a957600435600052609e602052602060018060a01b0360406000205416604051908152f35b346103a9576020806003193601126103a95760043590612951600092808452609d83526113d1604085205415156149be565b604051918360a3549061296382612f24565b916001908181169081156129c9575060011461298c575b610505866104f981610ec88b8a614bfd565b909192955060a382528582205b8383106129b65750505082019092019181610ec88261050561297a565b8054868401880152918601918101612999565b60ff19168588015250505080151502830101925081610ec88261050561297a565b346103a9576129f836610865565b90612a0e60018060a01b03606a54163314613a10565b6001600160401b038211610d8657600160401b8211610d865760a4548260a455808310612a9e575b5060a460009081529190600080516020615f2b8339815191526020845b848110612a8257857f69a14dc09c71917f03857a09574ce712b7e73c083e26968c14ca72da507fa14e8180a180f35b600190828535612a91816105bd565b9501948185015501612a53565b60a4600052612ac190600080516020615f2b833981519152908101908401612f5e565b38612a36565b60403660031901126103a957600435612adf816105bd565b602435612b1666ffffffffffffff612b0360ac5466ffffffffffffff9060a01c1690565b16612b0f811515613ef4565b4211613f31565b60ad54612b6d612b326001600160601b038360601c1684613296565b610adc60675493612023610ad3612b498888613aa4565b9263ffffffff612b6260a65463ffffffff9060d81c1690565b9160c01c1690613c3b565b612b78323314613cd2565b612b853460a0540160a055565b60005b828110612b9157005b80610bf9612ba2612bac9385613aa4565b6107813382614735565b612b88565b346103a95760403660031901126103a957602060ff612c0d600435612bd5816105bd565b60243590612be2826105bd565b60018060a01b03166000526069845260406000209060018060a01b0316600052602052604060002090565b54166040519015158152f35b60003660031901126103a95761044f6143d5565b346103a95760003660031901126103a957602066ffffffffffffff60aa5460a01c16604051908152f35b346103a95760203660031901126103a957600435612c74816105bd565b606a546001600160a01b0390612c8d9082163314613a10565b811615612c9d5761044f90615dc9565b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b346103a95760603660031901126103a957600435612d0e816105bd565b60243590612d1b826105bd565b6044356001600160401b0381116103a957612d3a903690600401610e08565b60005b815181101561044f5780610bf9612d57612d6c9385613d96565b51612d65610a2582336158f6565b86866159d2565b612d3d565b346103a95760203660031901126103a957600435612d8e816106bf565b612da360018060a01b03606a54163314613a10565b60675462ffffff821690811115612e43577f291346a9a1a36b98232bf8d9776ead3b0666a0a277b084d36170daab32d1c3c591612df96119cb92612df3610ad360a65463ffffffff9060d81c1690565b116151f9565b612e2d612e086117cb83615230565b60a6805463ffffffff60d81b191660d89290921b63ffffffff60d81b16919091179055565b60405162ffffff90911681529081906020820190565b60405162461bcd60e51b8152602060048201526007602482015266546f6f206c6f7760c81b6044820152606490fd5b15612e7957565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b903590601e19813603018212156103a957018035906001600160401b0382116103a9576020019181360383136103a957565b60405190612f1482610da6565b60008252565b356104aa816105bd565b90600182811c92168015612f54575b6020831014612f3e57565b634e487b7160e01b600052602260045260246000fd5b91607f1691612f33565b818110612f69575050565b60008155600101612f5e565b90601f8211612f82575050565b610def9160656000526020600020906020601f840160051c83019310612fb0575b601f0160051c0190612f5e565b9091508190612fa3565b90601f8211612fc7575050565b610def9160a36000526020600020906020601f840160051c83019310612fb057601f0160051c0190612f5e565b90601f8211613001575050565b610def9160666000526020600020906020601f840160051c83019310612fb057601f0160051c0190612f5e565b90601f821161303b575050565b610def9160a26000526020600020906020601f840160051c83019310612fb057601f0160051c0190612f5e565b91906001600160401b038111610d865761308c8161308760a254612f24565b61302e565b6000601f82116001146130c6578192936000926130bb575b50508160011b916000199060031b1c19161760a255565b0135905038806130a4565b60a2600052601f198216937faaf4f58de99300cfadc4585755f376d5fa747d5bc561d5bd9d710de1f91bf42d91805b86811061312d5750836001959610613113575b505050811b0160a255565b0135600019600384901b60f8161c19169055388080613108565b909260206001819286860135815501940191016130f5565b91906001600160401b038111610d86576131648161196460a354612f24565b6000601f821160011461319e57819293600092613193575b50508160011b916000199060031b1c19161760a355565b01359050388061317c565b60a3600052601f198216937f60859188cffe297f44dde29f2d2865634621f26215049caeb304ccba566a8b1791805b86811061320557508360019596106131eb575b505050811b0160a355565b0135600019600384901b60f8161c191690553880806131e0565b909260206001819286860135815501940191016131cd565b903590601e19813603018212156103a957018035906001600160401b0382116103a957602001918160051b360383136103a957565b634e487b7160e01b600052601160045260246000fd5b600281901b91906001600160fe1b038116036107a257565b906007820291808304600714901517156107a257565b818102929181159184041417156107a257565b6001600160401b038211610d8657600160401b8211610d865760a4548260a45580831061330b575b5060a46000526020806000209060005b8481106132ef575050505050565b600190828535956132ff876105bd565b019481850155016132e1565b60a460005261332e90600080516020615f2b833981519152908101908401612f5e565b386132d1565b3566ffffffffffffff811681036103a95790565b63ffffffff8116036103a957565b356104aa81613348565b356001600160601b03811681036103a95790565b356104aa816106bf565b613851610360610def9261339b6133958280612ed5565b90613068565b6133b16133ab6020830183612ed5565b90613145565b6133c76133c1604083018361321d565b906132a9565b606081013560a5556134006133de60808301612f1a565b60a680546001600160a01b0319166001600160a01b0392909216919091179055565b61343a61340f60a08301613334565b60a6805466ffffffffffffff60a01b191660a09290921b66ffffffffffffff60a01b16919091179055565b613449612e0860c08301613356565b61347a61345860e08301612f1a565b60a780546001600160a01b0319166001600160a01b0392909216919091179055565b6134af61348a6101008301613360565b60a780546001600160a01b031660a09290921b6001600160a01b031916919091179055565b6134e16134bf6101208301612f1a565b60a880546001600160a01b0319166001600160a01b0392909216919091179055565b6135166134f16101408301613360565b60a880546001600160a01b031660a09290921b6001600160a01b031916919091179055565b6135486135266101608301612f1a565b60a980546001600160a01b0319166001600160a01b0392909216919091179055565b61357b6135586101808301613374565b60a9805462ffffff60a01b191660a09290921b62ffffff60a01b16919091179055565b6135ae61358b6101a08301613374565b60a9805462ffffff60b81b191660b89290921b62ffffff60b81b16919091179055565b6135e16135be6101c08301613374565b60a9805462ffffff60d01b191660d09290921b62ffffff60d01b16919091179055565b6136166135f16101e08301613374565b60a980546001600160e81b031660e89290921b6001600160e81b031916919091179055565b6136486136266102008301612f1a565b60aa80546001600160a01b0319166001600160a01b0392909216919091179055565b6136836136586102208301613334565b60aa805466ffffffffffffff60a01b191660a09290921b66ffffffffffffff60a01b16919091179055565b6136b86136936102408301613356565b60aa805463ffffffff60d81b191660d89290921b63ffffffff60d81b16919091179055565b6136c86109076102608301612f1a565b6137036136d86102808301613334565b60ab805466ffffffffffffff60a01b191660a09290921b66ffffffffffffff60a01b16919091179055565b6137386137136102a08301613356565b60ab805463ffffffff60d81b191660d89290921b63ffffffff60d81b16919091179055565b61376a6137486102c08301612f1a565b60ac80546001600160a01b0319166001600160a01b0392909216919091179055565b6137a561377a6102e08301613334565b60ac805466ffffffffffffff60a01b191660a09290921b66ffffffffffffff60a01b16919091179055565b6137da6137b56103008301613356565b60ac805463ffffffff60d81b191660d89290921b63ffffffff60d81b16919091179055565b6138066137ea6103208301613360565b6001600160601b03166001600160601b031960ad54161760ad55565b61384b6138166103408301613360565b60ad80546bffffffffffffffffffffffff60601b191660609290921b6bffffffffffffffffffffffff60601b16919091179055565b01613356565b60ad805463ffffffff60c01b191660c09290921b63ffffffff60c01b16919091179055565b61388a6138838280612ed5565b3691611aa6565b6040519061389782610d6b565b600782526020660e13905410549560ca1b818401526138c660ff60005460081c166138c181615435565b615435565b8151916001600160401b038311610d86576138eb836138e6606554612f24565b612f75565b81601f84116001146139805750918061394395949261392694600092613975575b50508160011b916000199060031b1c191617606555615495565b61393e61393961076f6101608401612f1a565b615db0565b61337e565b6001600160a01b0381166139545750565b60ab80546001600160a01b0319166001600160a01b03909216919091179055565b01519050388061390c565b60656000529190601f1984167f8ff97419363ffd7000167f130ef7168fbea05faf9251824ca5043f113cc6a7c7936000905b8282106139f857505092600192859261392696613943999896106139df575b505050811b01606555615495565b015160001960f88460031b161c191690553880806139d1565b806001869782949787015181550196019401906139b2565b15613a1757565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b90600182018092116107a257565b90600282018092116107a257565b907f060606060606060606060606060606060606060606060606060606060606060682018092116107a257565b919082018092116107a257565b15613ab857565b60405162461bcd60e51b815260206004820152600a602482015269135a5b9d1959081bdd5d60b21b6044820152606490fd5b15613af157565b60405162461bcd60e51b815260206004820152601460248201527309ad2dce840dac2f040ccdeeae440e0cae440e8f60631b6044820152606490fd5b15613b3457565b60405162461bcd60e51b815260206004820152601b60248201527f416c6c6f77206c697374206d696e74206e6f74207374617274656400000000006044820152606490fd5b15613b8057565b60405162461bcd60e51b8152602060048201526015602482015274105b1b1bddc81b1a5cdd081b5a5b9d08195b991959605a1b6044820152606490fd5b15613bc457565b60405162461bcd60e51b8152602060048201526011602482015270139bdd081bdb88185b1b1bddc81b1a5cdd607a1b6044820152606490fd5b15613c0457565b60405162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e4818db185a5b5959608a1b6044820152606490fd5b63ffffffff91821690821603919082116107a257565b15613c5857565b60405162461bcd60e51b815260206004820152600d60248201526c4e6f7420617661696c61626c6560981b6044820152606490fd5b15613c9457565b60405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a5908199d5b991cc81c1c9bdd9a59195960521b6044820152606490fd5b15613cd957565b60405162461bcd60e51b81526020600482015260136024820152724e6f20636f6e7472616374206d696e74696e6760681b6044820152606490fd5b929091906000915b8451831015613d6957613d2f8386613d96565b5190600082821015613d575750600052602052613d5160406000205b92613d71565b91613d1c565b604091613d5193825260205220613d4b565b915092501490565b60001981146107a25760010190565b634e487b7160e01b600052603260045260246000fd5b8051821015613daa5760209160051b010190565b613d80565b15613db657565b60405162461bcd60e51b815260206004820152601a60248201527f4d696e742070617373206d696e74206e6f7420737461727465640000000000006044820152606490fd5b15613e0257565b60405162461bcd60e51b8152602060048201526014602482015273135a5b9d081c185cdcc81b5a5b9d08195b99195960621b6044820152606490fd5b15613e4557565b60405162461bcd60e51b81526020600482015260116024820152704d696e74206174206c65617374206f6e6560781b6044820152606490fd5b9190811015613daa5760051b0190565b908160209103126103a957516104aa816105bd565b6040513d6000823e3d90fd5b15613eb657565b60405162461bcd60e51b8152602060048201526016602482015275135a5b9d081c185cdcc8185b1c9958591e481d5cd95960521b6044820152606490fd5b15613efb57565b60405162461bcd60e51b815260206004820152600e60248201526d139bc81c1d589b1a58c81b5a5b9d60921b6044820152606490fd5b15613f3857565b60405162461bcd60e51b8152602060048201526017602482015276141d589b1a58c81b5a5b9d081b9bdd081cdd185c9d1959604a1b6044820152606490fd5b15613f7e57565b60405162461bcd60e51b8152602060048201526019602482015278109a59191a5b99c81c1a185cd9481b9bdd081cdd185c9d1959603a1b6044820152606490fd5b15613fc657565b60405162461bcd60e51b81526020600482015260156024820152744e6f20636f6e74726163742072657665616c696e6760581b6044820152606490fd5b1561400a57565b60405162461bcd60e51b815260206004820152601360248201527241756374696f6e20696e2070726f677265737360681b6044820152606490fd5b1561404c57565b60405162461bcd60e51b815260206004820152601060248201526f105b1c9958591e481c995d99585b195960821b6044820152606490fd5b60ff66ffffffffffffff806140a560ac5466ffffffffffffff9060a01c1690565b168015614203574211806141c0575b6140bd90613f77565b6140c8323314613fbf565b6140d860b1549182164211614003565b60381c1615806141b5575b6141a8575b6141816067546140fa610ac282613a5b565b61410660b05415614045565b6141103382614735565b61412482600052609d602052604060002090565b5561415c3361413d83600052609e602052604060002090565b80546001600160a01b0319166001600160a01b03909216919091179055565b60b1805467ffffffffffffffff1916905561417c600060ae55600060af55565b60b055565b7fabfa50b1969c21cf8a6ef98cc34a97b3c5ce9fe16e1268ffaa57c272faccbcab600080a1565b6141b0614617565b6140e8565b5060af5415156140e3565b506140bd6141cf606754613a5b565b6141fa610ad36141e860a65463ffffffff9060d81c1690565b60ad5460c01c63ffffffff1690613c3b565b111590506140b4565b50614227614220610a5460a65466ffffffffffffff9060a01c1690565b4211613f77565b6140bd565b1561423357565b60405162461bcd60e51b815260206004820152601260248201527114995d99585b081c1a5958d948199a5c9cdd60721b6044820152606490fd5b1561427457565b60405162461bcd60e51b815260206004820152601d60248201527f426964206973206c6f776572207468616e206d696e696d756d206269640000006044820152606490fd5b156142c057565b60405162461bcd60e51b81526020600482015260136024820152724e6f20636f6e74726163742062696464696e6760681b6044820152606490fd5b1561430257565b60405162461bcd60e51b815260206004820152602960248201527f426964206d757374206265203e2035252067726561746572207468616e2063756044820152681c9c995b9d08189a5960ba1b6064820152608490fd5b6040519061436682610d6b565b60ae546001600160a01b0316825260af546020830152565b1561438557565b60405162461bcd60e51b815260206004820152600d60248201526c105d58dd1a5bdb88195b991959609a1b6044820152606490fd5b91909166ffffffffffffff808094169116019182116107a257565b6143f66143ee606754600052609d602052604060002090565b54151561422c565b614410614408610aa360a85460a01c90565b34101561426d565b61441b3233146142b9565b61443561442e60af546014810490613aa4565b34116142fb565b61443d614359565b61446d614448610de2565b3380825234602090920182905260ae80546001600160a01b031916909117905560af55565b66ffffffffffffff8061448860b15466ffffffffffffff1690565b161561459357600080809381936144a760b15466ffffffffffffff1690565b9081166144b581421061437e565b6144d46144ce610ad360ac5463ffffffff9060d81c1690565b42613aa4565b1161454e575b5080516020906144f2906001600160a01b031661076f565b91015190828215614545575bf115610c30575b6040805160ae546001600160a01b0316815260af5460208201527ffa040d55a6992a6143e6ea8c968e9530213b85d9a399be45045c7f5d5065bd579190a1565b506108fc6144fe565b61457161458d9161456b610ad360ab5463ffffffff9060d81c1690565b906143ba565b66ffffffffffffff1666ffffffffffffff1960b154161760b155565b386144da565b6145c39150614571906145b2610ad360aa5463ffffffff9060d81c1690565b429091160166ffffffffffffff1690565b614505565b156145cf57565b60405162461bcd60e51b8152602060048201526013602482015272105d58dd1a5bdb881b9bdd081cdd185c9d1959606a1b6044820152606490fd5b919082039182116107a257565b61463c66ffffffffffffff61463460b15466ffffffffffffff1690565b1615156145c8565b60ae546001600160a01b031661466461076f6112aa60b054600052609e602052604060002090565b6001600160a01b03918216036146d757600080808060af5461469d6117ec6117e46117dd6117d36117cb60a95462ffffff9060a01c1690565b60ae546146b2906001600160a01b031661076f565b8282156146ce575bf115610c3057610def90611837600060b055565b506108fc6146ba565b610def906146ec6117ec60af5460a054613aa4565b61182d565b156146f857565b60405162461bcd60e51b8152602060048201526015602482015274105d58dd1a5bdb881b9bdd0818dbdb98db1d591959605a1b6044820152606490fd5b9060405190602082019283526001600160601b03199060601b1660408201526000194301406054820152600119430140607482015260031943014060948201524460b48201524160601b60d482015260c8815261010081018181106001600160401b03821117610d865760405251902090565b156147af57565b60405162461bcd60e51b815260206004820152600b60248201526a139bdd08185b1b1bddd95960aa1b6044820152606490fd5b156147e957565b60405162461bcd60e51b815260206004820152600f60248201526e42616c616e6365206973207a65726f60881b6044820152606490fd5b9061482a8261557a565b80156148915761483981610df1565b906148476040519283610dc1565b808252601f1961485682610df1565b0136602084013760005b81811061486e575090925050565b8061487c61488c928761538c565b6148868286613d96565b52613d71565b614860565b5090506040516148a081610da6565b60008152600036813790565b60a454811015613daa5760a460005260206000200190600090565b606754811015613daa57606760005260206000200190600090565b90916000906067908154925b81811061490057505050505050600190565b61490b818388613e7e565b3584811015613daa5760008481526020902001546001600160a01b03908116908616036149405761493b90613d71565b6148ee565b505050505050600090565b606754600160401b811015610d86578161496e82600161498d94016067556148c7565b90919082549060031b9160018060a01b03809116831b921b1916179055565b6001600160a01b031660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4565b156149c557565b60405162461bcd60e51b815260206004820152600f60248201526e151bdad95b881b9bdd08199bdd5b99608a1b6044820152606490fd5b81601f820112156103a9578051614a1281611a8b565b92614a206040519485610dc1565b818452602082840101116103a9576104aa9160208085019101610451565b9060209081838203126103a95782516001600160401b03938482116103a957019080601f830112156103a9578151614a7581610df1565b94604090614a8582519788610dc1565b828752858088019360051b860101948486116103a957868101935b868510614ab257505050505050505090565b84518381116103a95782019084601f1983890301126103a957845190614ad782610d6b565b89830151614ae4816105bd565b825285830151918583116103a957614b03898c809695819601016149fc565b83820152815201940193614aa0565b602080828403126103a95781516001600160401b03928382116103a957019260409283858303126103a957835194614b4986610d6b565b80518652838101519182116103a9570181601f820112156103a957805191614b7083610df1565b94614b7d81519687610dc1565b83865284860191856060809602850101938185116103a9578601925b848410614bac5750505050505082015290565b85848303126103a9578686918451614bc381610d8b565b8651614bce816105bd565b815282870151614bdd81613348565b8382015285870151614bee81613348565b86820152815201930192614b99565b90614c1060209282815194859201610451565b0190565b6030610def919392936040519481614c36879351809260208087019101610451565b82016c6177616974206c73323536282760981b6020820152614c62825180936020602d85019101610451565b016227293b60e81b602d820152036010810185520183610dc1565b906020828203126103a95781516001600160401b0381116103a9576104aa92016149fc565b6020610def919392936040519481614cc38793518092868087019101610451565b8201614cd782518093868085019101610451565b01038085520183610dc1565b90610def603660405180947519185d184e9d195e1d0bda1d1b5b0ed8985cd94d8d0b60521b6020830152614d208151809260208686019101610451565b8101036016810185520183610dc1565b60405190614d3d82610d8b565b604082527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040837f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201520152565b60405190614d9c82610d8b565b602a82526040366020840137565b90614db482611a8b565b614dc16040519182610dc1565b8281528092614dd2601f1991611a8b565b0190602036910137565b805115614eae57614deb614d30565b614e0f614e0a614e05614dfe8551613a69565b6003900490565b613268565b614daa565b9160208301918182518301915b828210614e5c57505050600390510680600114614e4957600214614e3e575090565b603d90600019015390565b50603d9081600019820153600119015390565b9091936004906003809401938451600190603f9082828260121c16880101518553828282600c1c16880101518386015382828260061c1688010151600286015316850101519082015301939190614e1c565b506104aa612f07565b6000908072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b80821015614fe7575b506d04ee2d6d415b85acef810000000080831015614fd8575b50662386f26fc1000080831015614fc9575b506305f5e10080831015614fba575b5061271080831015614fab575b506064821015614f9b575b600a80921015614f91575b600190816021614f49828701614daa565b95860101905b614f5b575b5050505090565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a835304918215614f8c57919082614f4f565b614f54565b9160010191614f38565b9190606460029104910191614f2d565b60049193920491019138614f22565b60089193920491019138614f15565b60109193920491019138614f06565b60209193920491019138614ef4565b604093508104915038614edb565b6150166001600160801b031961500c83821661504f565b9260801b1661504f565b6040519161060f60f31b60208401526022830152604282015260428152608081018181106001600160401b03821117610d865760405290565b8060401c9063ffffffff60401b821663ffffffff60c01b82161760201c9163ffffffff60601b169063ffffffff60e01b1617178060101c907bff00000000000000ff00000000000000ff00000000000000ff0000007aff00000000000000ff00000000000000ff00000000000000ff000083167eff00000000000000ff00000000000000ff00000000000000ff00000000000083161760081c92169078ff00000000000000ff00000000000000ff00000000000000ff60381b1617177f0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f007e0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f8260081c169160041c16177f30303030303030303030303030303030303030303030303030303030303030308181018091116107a2576151c17f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f6151bb6151b56104aa95613a77565b60041c90565b16613280565b90613aa4565b908060209392818452848401376000828201840152601f01601f1916010190565b9160206104aa9381815201916151c7565b1561520057565b60405162461bcd60e51b81526020600482015260086024820152670a8dede40d0d2ced60c31b6044820152606490fd5b90600162ffffff809316019182116107a257565b600b60fa1b815260010190565b908151811015613daa570160200190565b80156107a2576000190190565b1561527657565b606460405162461bcd60e51b815260206004820152602060248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152fd5b6152c2614d8f565b90815115613daa57603060208301538151600190811015613daa5790607860218401536029915b8083116152fc57506104aa91501561526f565b90600f8116906010821015613daa57615339916f181899199a1a9b1b9c1cb0b131b232b360811b901a61532f8587615251565b5360041c92615262565b91906152e9565b60809060208152602b60208201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560408201526a74206f6620626f756e647360a81b60608201520190565b906153968261557a565b81101561541c576000908192606754935b8481106153cb5760405162461bcd60e51b8152806153c760048201615340565b0390fd5b6153da61076f612742836148c7565b6001600160a01b038316146153f8575b6153f390613d71565b6153a7565b9282810361540857505050905090565b6154146153f391613d71565b9390506153ea565b60405162461bcd60e51b8152806153c760048201615340565b1561543c57565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b9081516001600160401b038111610d86576154ba816154b5606654612f24565b612ff4565b602080601f83116001146154f657508192936000926154eb575b50508160011b916000199060031b1c191617606655565b0151905038806154d4565b6066600052601f198316949091907f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e94354926000905b878210615562575050836001959610615549575b505050811b01606655565b015160001960f88460031b161c1916905538808061553e565b8060018596829496860151815501950193019061552a565b6001600160a01b031680156155d757606754600091825b82811061559e5750505090565b6155ad61076f612742836148c7565b82146155c2575b6155bd90613d71565b615591565b926155cf6155bd91613d71565b9390506155b4565b60405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608490fd5b606754811015613daa5760676000527f9787eeb91fe3101235e4a76063c7023ecb40f923f97916639c598592fa30d6ae01546001600160a01b031680156156735790565b60405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608490fd5b156156d157565b60405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776044820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b6064820152608490fd5b615740816158ab565b15615760576000908152606860205260409020546001600160a01b031690565b60405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608490fd5b156157c157565b60405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6044820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b6064820152608490fd5b90615844939291615834610a2584336158f6565b61583f8383836159d2565b615c0d565b1561584b57565b60405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608490fd5b606754811090816158ba575090565b9015613daa5760676000527f9787eeb91fe3101235e4a76063c7023ecb40f923f97916639c598592fa30d6ae01546001600160a01b0316151590565b6158ff826158ab565b156159785761590d8261562f565b6001600160a01b038281168282168114949091908515615960575b505050821561593657505090565b6001600160a01b0316600090815260696020526040902060ff925061595b919061064c565b541690565b61596d9192939550615737565b161491388080615928565b60405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608490fd5b6159db8361562f565b6001600160a01b0391821691908116829003615a88578216918215615a3757615a1090615a0785615adf565b61496e856148c7565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4565b60405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b60405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608490fd5b600081815260686020526040812080546001600160a01b03191690556001600160a01b03615b0c8361562f565b167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258280a4565b600082815260686020526040902080546001600160a01b0319166001600160a01b0383161790556001600160a01b0380615b6c8461562f565b169116907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a4565b908160209103126103a957516104aa81610397565b6001600160a01b0391821681529116602082015260408101919091526080606082018190526104aa92910190610474565b3d15615c08573d90615bee82611a8b565b91615bfc6040519384610dc1565b82523d6000602084013e565b606090565b92909190823b15615d0e57615c40926020926000604051809681958294630a85bd0160e11b9a8b85523360048601615bac565b03926001600160a01b03165af160009181615cde575b50615cd057615c63615bdd565b80519081615ccb5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608490fd5b602001fd5b6001600160e01b0319161490565b615d0091925060203d8111615d07575b615cf88183610dc1565b810190615b97565b9038615c56565b503d615cee565b50505050600190565b90602080920151918251928190604092835195600091825b828410615d4d575050505050601f8019918281018652011683019052565b90919293969594828560051b8901015180518785830151920151813b808211615d92575082849392600195938e930394859301903c0194019291909693949596615d2f565b9260849386936386d14d8960e01b8552600452602452604452606452fd5b610def90615dc960ff60005460081c166138c181615435565b606a80546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b615e94615ea4602e604051615e4f602182602081019760008952615e3f8151809260208686019101610451565b8101036001810184520182610dc1565b8051946040519485926020840197606360f81b895263ffffffff60e01b9060e01b1660218501526880600e6000396000f360b81b602585015251809285850190610451565b810103600e810184520182610dc1565b51906000f0906001600160a01b03821615615ebb57565b60405163046a55db60e11b8152600490fd5b90813b8015615f145780600111615f14576000190160011980821015615f0d57505b600160405193601f19603f840116850160405282855260208501903c565b9050615eef565b509050604051615f2381610da6565b600081529056fee434dc35da084cf8d7e8186688ea2dacb53db7003d427af3abf351bd9d0a4e8da2646970667358221220590f6538a61208647c61924cd45e0da49d6570caaf26118f078b9db4ea8fb60664736f6c63430008130033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.