Feature Tip: Add private address tag to any address under My Name Tag !
ERC-721
Overview
Max Total Supply
8,281 GDBLK
Holders
2,775
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 GDBLKLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
goodblocks
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /* ██████ ██████ ██████ ██████ ██████ ██ ██████ ██████ ██ ██ ███████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███ ██ ██ ██ ██ ██ ██ ██████ ██ ██ ██ ██ █████ ███████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ██████ ██████ ██████ ██████ ███████ ██████ ██████ ██ ██ ███████ by @0xSomeGuy a collection made with ❤ for creators, innovators, and builders having real world impact and doing good. ...or anyone who supports that stuff too. 👊 shoutouts/credits to other projects/contract/devs/people: @OnChainMonkey: @huuep @NuclearNerds: @nftchance (Mimetic Metadata), masonnft, @squeebo_nft Azuki: @ChiruLabs (ERC721A) @AnonymiceNFT: @_MouseDev and Kiro @OnChainKevinNFT @HumansNft @FlowerGirlsNFT @developer_dao section headers made with: https://patorjk.com/software/taag (ANSI Regular) */ import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol'; import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import '@openzeppelin/contracts/utils/Address.sol'; import '@openzeppelin/contracts/utils/Strings.sol'; error StopTryingToApproveIfYoureNotTheOwnerOrApproved(); error WhyAreYouTryingToApproveYourself(); error YoureTheOwnerYouDontNeedApprovalDuh(); error CantGetApprovalsForTokensThatDontExist(); error BalanceOfZeroAddressNotAllowedItsComplicated(); error LoveTheSupportButCantMintThatMany(); error GenerationAddressNotValidWhoops(); error UhOhTheGenerationYouRequestedIsNotEnabled(); error HoldYourHorsesNextGenerationIsNotEnabled(); error SeriouslyYouDontEvenHaveThatMuchToSend(); error NotTheRightAmountToUnlockTryAgain(); error ReallyWantToMintForYouButNotTheRightFunds(); error TheresNoGenerationsLessThanZeroDude(); error LoveTheExcitementButMintIsNotActive(); error SorryFriendContractsCantMint(); error WeWouldBreakIfWeMintedThisMany(); error HowCanYouEvenMintLessThanOne(); error MintingToZeroAddressWouldCauseHavoc(); error SorryYouCantAbandonOwnershipToTheZeroAddress(); error WeReallyNeedTheContractOwnerToDoThis(); error WeKnowYoureTheOwnerAndAllButYouCantMintThatMany(); error DangCouldntSendTheFundsForYou(); error StopTryingToChangeOtherPeoplesTokenGenerationYoureNotTheOwner(); error AreYouReallyTryingToSetTheGenerationForTokensThatDontExist(); error GottaUnlockThisGenerationBeforeYouSetItFriend(); error TokensThatDontExistDontHaveDataOrDoThey(); error ItsTheSameGenerationYoureNotChangingAnything(); error WhyAreYouTryingToTransferTheTokenIfYoureNotTheOwnerOrApproved(); error TheFromAddressNeedsToBeTheOwnerPlease(); error TransferToNonERC721ReceiverImplementer(); error PleaseDontTransferToTheZeroAddressThanks(); error DontMessWithOtherPeoplesTokensOnlyOwnersCanUnlockNextGeneration(); error CantGetTheUriForTokensThatArentEvenReal(); error SorryCouldntWithdrawYourFundsHomie(); /** @author @0xSomeGuy @notice this contract handles the multi generational ERC721 tokens for the goodblocks community @dev hit me up with any questions or feedback! dms always open. */ contract goodblocks is IERC721, IERC721Metadata, ReentrancyGuard { constructor() { _Owner = msg.sender; } using Address for address; using Strings for uint256; /* ███████ ████████ █████ ████████ ███████ ██ ██ █████ ██████ ███████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███████ ██ ███████ ██ █████ ██ ██ ███████ ██████ ███████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███████ ██ ██ ██ ██ ███████ ████ ██ ██ ██ ██ ███████ section for state variables in the contract sección de 'state variables' en el contrato */ // project information // información del proyecto uint256 constant CollectionSize = 8281; string public ProjectName = unicode"goodblocks"; string public ProjectSymbol = unicode"GDBLK"; string public ProjectDescription = unicode"create x innovate x impact. good vibes guaranteed. 👊💯"; /** @notice function to update project info función para cambiar la información del proyecto @param _newName new project name el nuevo nombre del proyecto @param _newSymbol new project symbol el nuevo símbolo del proyecto @param _newDesc new project description la nueva descripción del proyecto */ function updateProjectInfo(string memory _newName, string memory _newSymbol, string memory _newDesc) external onlyOwner { ProjectName = _newName; ProjectSymbol = _newSymbol; ProjectDescription = _newDesc; } // contract owner address private _Owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** @notice get contract owner obtener dueño del contrato @return address owner address dirección del dueño */ function owner() public view returns (address) { return _Owner; } /** @notice transfer contract ownership transferir la propiedad del contrato @param _newOwner address of new owner dirección de nuevo dueño/dueña */ function transferOwnership(address _newOwner) external onlyOwner { if(_newOwner == address(0)) revert SorryYouCantAbandonOwnershipToTheZeroAddress(); address oldOwner =_Owner; _Owner = _newOwner; emit OwnershipTransferred(oldOwner, _newOwner); } // mint variables // variables para el mint (acuñación) uint256 private constant StartTokenIndex = 0; uint256 private constant MaxReserve = 410; bool public IsMintActive = false; uint256 private ReserveUsed = 0; uint256 public GoodblockPrice = 0.05 ether; uint256 public MaxMintPerAddress = 7; uint256 public MaxFreePerAddress = 2; uint256 private CurrentTokenIndex = 0; uint256 public TotalMinted = 0; /** @notice update mint price cambiar precio @param _newPriceInWei new price in wei nuevo precio en wei */ function updateMintPrice(uint256 _newPriceInWei) external onlyOwner { GoodblockPrice = _newPriceInWei; } /** @notice update max mint per address cambiar mint máximo por dirección @param _newMaxPerAddress new max per address nuevo máximo por dirección */ function updateMaxMintPerAddress(uint256 _newMaxPerAddress) external onlyOwner { MaxMintPerAddress = _newMaxPerAddress; } /** @notice update max free per address cambiar máximo gratis por dirección @param _newMaxFreePerAddress new max per address nuevo máximo por dirección */ function updateMaxFreePerAddress(uint256 _newMaxFreePerAddress) external onlyOwner { MaxFreePerAddress = _newMaxFreePerAddress; } /** @notice struct for token data struct para datos del token @param activeGen active generation of token generación activa de token @param highestGenLevel highest generation unlocked for token generación más alta desbloqueada para token @param timesTransferred times token has been transferred (including non sale transfers) veces que se ha transferido el token (incluyendo las transferencias que no son de venta) @param ownedSince time token has been owned by currrent owner (property can be inherited from other token) tiempo que el token ha sido propiedad del propietario actual (se puede heredar de otro token) @param tokenOwner current owner of token (property can be inherited from other token) propietario actual del token (se puede heredar de otro token) @dev "tokenOwner" and "ownedSince" needs special logic due to batch mint approach, can also be inhertied by another token "tokenOwner" y "ownedSince" necesita una lógica especial por el enfoque de acuñar por lotes, tambien se puede heredar de otro token */ struct TokenData { uint8 activeGen; uint8 highestGenLevel; uint64 timesTransferred; uint64 ownedSince; address tokenOwner; } /** @notice struct for address data struct para datos de cada dirección @param mintedCount number of minted tokens for this address número de tokens acuñados para esta dirección @param balance current address balance of goodblock tokens balance de tokens goodblock do un dirección */ struct AddressData { uint8 mintedCount; uint16 balance; } /** @notice struct for generation data struct para datos de cada generación @param isEnabled is generation enabled está habilitada la generación @param genAddress address of generation dirección de generación @param unlockCostInWei cost to unlock in WEI costo para desbloquear en WEI */ struct GenerationData { bool isEnabled; address genAddress; uint256 unlockCostInWei; } // maps each token to token data // asigna cada token a datos de token mapping(uint256 => TokenData) private TokenToDataMap; // maps each address to address data // asigna cada dirección a los datos de dirección mapping(address => AddressData) public AddressToDataMap; // maps each generation to generation data // asigna cada generación a los datos de la generación mapping(uint256 => GenerationData) private GenerationToDataMap; // maps each token to approved addresses // asigna cada token a direcciones aprobadas mapping(uint256 => address) private TokenToApprovedMap; // maps each owner to operator approvals // asigna cada propietario a las aprobaciones del operador mapping(address => mapping(address => bool)) private OperatorApprovals; // variables to add times transferred to metadata // variables para agregar tiempos transferidos a metadatos string[] private TransferCountBucketStrings; uint256[] private TransferCountBuckets; /** @notice updates the count and associated metadata string actualiza el conteo y los metadatos asociada @param _index index to update índice para actualizar @param _transferMax max transfer count for this bucket número máximo de transferencias para este grupo @param _traitName how trait appears in metadata texto para metadatos */ function updateTransferBucket(uint256 _index, uint256 _transferMax, string memory _traitName) external onlyOwner returns (string[] memory) { if(_index >= TransferCountBucketStrings.length) { TransferCountBucketStrings.push(_traitName); TransferCountBuckets.push(_transferMax); } else { TransferCountBucketStrings[_index] = _traitName; TransferCountBuckets[_index] = _transferMax; } return TransferCountBucketStrings; } // variables to add owned since to metadata // variables para agregar la duración de la propiedad a los metadatos string[] private OwnedSinceBucketStrings; uint256[] private OwnedSinceBuckets; /** @notice updates the count and associated metadata string actualiza el conteo y los metadatos asociada @param _index index to update índice para actualizar @param _timeMax max time for this bucket tiempo máximo para este grupo @param _traitName how trait appears in metadata texto para metadatos */ function updateOwnedSinceBucket(uint256 _index, uint256 _timeMax, string memory _traitName) external onlyOwner returns (string[] memory) { if(_index >= OwnedSinceBucketStrings.length) { OwnedSinceBucketStrings.push(_traitName); OwnedSinceBuckets.push(_timeMax); } else { OwnedSinceBucketStrings[_index] = _traitName; OwnedSinceBuckets[_index] = _timeMax; } return OwnedSinceBucketStrings; } /* ███ ███ ██████ ██████ ██ ███████ ██ ███████ ██████ ███████ ████ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ █████ ██ █████ ██████ ███████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ██████ ██ ██ ██ ███████ ██ ██ ███████ */ modifier onlyOwner() { if(msg.sender !=_Owner) revert WeReallyNeedTheContractOwnerToDoThis(); _; } /* ███████ ██████ ██████ ██ ██████ ███████ ██ ██ ██ ██ ███ ██ ██ █████ ██████ ██ ██ ███████ ███████ ██ ██ ██ ██ ██ ██ ██ ██ ███████ ██ ██ ██████ ██ ██████ ███████ */ /** @notice see {IERC165-supportsInterface} */ function supportsInterface(bytes4 interfaceId) public pure override(IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId; } /* ███████ ██████ ██████ ███████ ██████ ██ ██ ██ ██ ██ ██ ██ ███ █████ ██████ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██ ███████ ██ ██ ██████ ██ ███████ ██ */ /** @notice see {IERC721-balanceOf} @notice gets the balance of an address @param _owner address to be checked dirección a revisar @return uint256 of tokens owned by address balance de tokens de la dirección */ function balanceOf(address _owner) public view override returns (uint256) { if (_owner == address(0)) revert BalanceOfZeroAddressNotAllowedItsComplicated(); return uint256(AddressToDataMap[_owner].balance); } /** @notice see {IERC721-ownerOf} @notice gets the owner of a specific token obtiene el dueño/la dueña de un token específico @param _tokenId token id to get owner identificación del token para obtener el propietario @return address address of token owner dirección de el dueño/la dueña del token */ function ownerOf(uint256 _tokenId) public view override returns (address) { return getTokenData(_tokenId).tokenOwner; } /** @notice see {IERC721-safeTransferFrom} @notice safely transfers tokens to addresses and contracts transfiere tokens de forma segura a carteras y contratos @param _from the originating address la dirección de origen @param _to the receiving address la dirección de recepción @param _tokenId token to be transferred token a transferir @param _data any data with the transfer cualquier dato con la transacción */ function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory _data) public override { // transfer token // token de transferencia _transferToken(_from, _to, _tokenId); // if _to is contract, ensure it implements {IERC721Receiver-onERC721Received} // si _to es un contrato, asegúrese de que implemente {IERC721Receiver-onERC721Received} if (_to.isContract() && !_checkContractOnERC721Received(_from, _to, _tokenId, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } /** @notice see {IERC721-safeTransferFrom} @notice see above véa más arriba */ function safeTransferFrom(address _from, address _to, uint256 _tokenId) public override { safeTransferFrom(_from, _to, _tokenId, ''); } /** @notice see {IERC721-transferFrom} @notice transfers tokens transfiere tokens @param _from the originating address la dirección de origen @param _to the receiving address la dirección de recepción @param _tokenId token to be transferred token a transferir */ function transferFrom(address _from, address _to, uint256 _tokenId) public override { _transferToken(_from, _to, _tokenId); } /** @notice see {IERC721-safeTransferFrom} @notice grant approval for another address to transfer a token aprobador otra dirección para transferir un token @param _to address to approve dirección para aprobar @param _tokenId token to approve for transfer token para aprobar la transferencia */ function approve(address _to, uint256 _tokenId) public override { // get token owner // obtener dueño/dueña de token address tokenOwner = getTokenData(_tokenId).tokenOwner; // check if owner is trying to approve self // verificar si el dueño/la dueña está tratando de aprobarse a sí mismo if (_to == tokenOwner) revert YoureTheOwnerYouDontNeedApprovalDuh(); // check if owner or operator is calling function // verificar si el dueño/la dueña u operador está llamando a la función if (msg.sender != tokenOwner && !isApprovedForAll(tokenOwner, msg.sender)) revert StopTryingToApproveIfYoureNotTheOwnerOrApproved(); // set approval // establecer aprobación _approve(_to, _tokenId, tokenOwner); } /** @notice see {IERC721-setApprovalForAll} @param _operator operator to approve operador para aprobar @param _approvedStatus status of operator approval estado de aprobación del operador */ function setApprovalForAll(address _operator, bool _approvedStatus) public override { // check if operator is trying to approve self // verificar si el operador está tratando de aprobarse a sí mismo if (_operator == msg.sender) revert WhyAreYouTryingToApproveYourself(); OperatorApprovals[msg.sender][_operator] = _approvedStatus; emit ApprovalForAll(msg.sender, _operator, _approvedStatus); } /** @notice see {IERC721-getApproved} @notice get approved address for token obtener dirección aprobada para token @param _tokenId token to check token para verificar @return address address of approved dirección de aprobado */ function getApproved(uint256 _tokenId) public view override returns (address) { // check token exists // verificar que existe el token if (!_exists(_tokenId)) revert CantGetApprovalsForTokensThatDontExist(); return TokenToApprovedMap[_tokenId]; } /** @notice see {IERC721-isApprovedForAll} @notice check if operator is approved for all compruebe si el operador está aprobado @param _owner address to check dirección para verificar @param _operator operator to check operador para verificar @return bool operator approval status estado de aprobación del operador */ function isApprovedForAll(address _owner, address _operator) public view override returns (bool) { return OperatorApprovals[_owner][_operator]; } /** @notice see {ERC721-_checkOnERC721Received} @notice check if target contract implements receiver @param _from the originating address la dirección de origen @param _to the receiving address la dirección de recepción @param _tokenId token to be transferred token a transferir @param _data any data with the transfer cualquier dato con la transacción @return bool whether the target address implements or not si la dirección de destino implementa o no */ function _checkContractOnERC721Received(address _from, address _to, uint256 _tokenId, bytes memory _data) private returns (bool) { try IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) returns (bytes4 retval) { return retval == IERC721Receiver(_to).onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert TransferToNonERC721ReceiverImplementer(); } else { assembly { revert(add(32, reason), mload(reason)) } } } } /* ███████ ██████ ██████ ███████ ██████ ██ ███ ███ ███████ ████████ █████ ██████ █████ ████████ █████ ██ ██ ██ ██ ██ ██ ███ ████ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ █████ ██████ ██ ██ █████ ██ █████ ██ ████ ██ █████ ██ ███████ ██ ██ ███████ ██ ███████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███████ ██ ██ ██████ ██ ███████ ██ ██ ██ ███████ ██ ██ ██ ██████ ██ ██ ██ ██ ██ */ /** @notice see {IERC721Metadata-name}. @notice returns the project name devuelve el nombre del proyecto */ function name() public view override returns (string memory) { return ProjectName; } /** @notice see {IERC721Metadata-symbol}. @notice returns the project symbol devuelve el símbolo del proyecto */ function symbol() public view override returns (string memory) { return ProjectSymbol; } /** @notice see {IERC721Metadata-tokenURI}. @notice returns the token uri containing image and metadata devuelve el token uri que contiene la imagen y los metadatos @param _tokenId token to retrieve token para recuperar @return string token uri (data) token uri (datos) */ function tokenURI(uint256 _tokenId) public view override returns (string memory) { // who's reading carefully? // quién está leyendo con atención? require(_tokenId != 12345678910111213, string(abi.encodePacked("interesting... ", rh))); // check token exists first // primero verificar que el token existe if (!_exists(_tokenId)) revert CantGetTheUriForTokensThatArentEvenReal(); // get token generation data // obtener datos de generación del token TokenData memory tokenData = getTokenData(_tokenId); address tokenGenAddress = GenerationToDataMap[tokenData.activeGen].genAddress; // check for valid gen address // verifica si hay una dirección de generación válida if (tokenGenAddress == address(0)) revert GenerationAddressNotValidWhoops(); // get times transferred bucket // obtener el grupo de veces transferidas string memory transferTrait = "?"; for(uint i=0; i<TransferCountBuckets.length; i++) { if(tokenData.timesTransferred < TransferCountBuckets[i]) { transferTrait = TransferCountBucketStrings[i]; break; } } // get owned since bucket // obtener el grupo de la duración de la propiedad string memory ownedSinceTrait = "?"; for(uint i=0; i<OwnedSinceBuckets.length; i++) { if(tokenData.ownedSince < OwnedSinceBuckets[i]) { ownedSinceTrait = OwnedSinceBucketStrings[i]; break; } } // generate token uri and metadata // generar token uri y metadata string memory tokenAttributes = string(abi.encodePacked( '{"trait_type": "Generations Unlocked", "value":"', Strings.toString(tokenData.highestGenLevel+1), '"},', '{"trait_type": "Active Generation", "value":"', Strings.toString(tokenData.activeGen), '"},', '{"trait_type": "Times Transferred", "value":"', transferTrait, '"},', '{"trait_type": "Owned Since", "value":"', ownedSinceTrait, '"}' )); string memory tokenMetadata = string(abi.encodePacked( '"ownedSince":"', Strings.toString(tokenData.ownedSince), '", "timesTransferred":"', Strings.toString(tokenData.timesTransferred), '"' )); iGoodblocksGen goodblocksGen = iGoodblocksGen(tokenGenAddress); return goodblocksGen.tokenGenURI(_tokenId, tokenMetadata, tokenAttributes); } /* ██████ ███████ ███ ██ ███████ ██████ █████ ████████ ██ ██████ ███ ██ ███████ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ███ █████ ██ ██ ██ █████ ██████ ███████ ██ ██ ██ ██ ██ ██ ██ ███████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ███████ ██ ████ ███████ ██ ██ ██ ██ ██ ██ ██████ ██ ████ ███████ */ /** @notice get data for generation by index obtener datos para la generación por índice @param _genIndex index of generation índice de generación @return GenerationData generation data datos de generación */ function getGenerationData(uint256 _genIndex) public view returns (GenerationData memory) { return GenerationToDataMap[_genIndex]; } /** @notice update the data for any generation (index starting at 0) cambiar los datos para cualquier generación (índice comienza en 0) @param _genIndex generation index índice de generación @param _isEnabled status of the generation estado de la generacion @param _genAddress rendering address for the generation (tokenURI points here) dirección de representación para la generación (tokenURI viene de aquí) @param _costInWei cost for unlocking this generation costo para desbloquear esta generación @dev all tokens start with a '0' index generation so the 'genesis' generation index should be 0 todos los tokens comienzan con una generación de índice '0', el índice de generación 'génesis' debe ser 0 */ function updateGeneration(uint256 _genIndex, bool _isEnabled, address _genAddress, uint256 _costInWei) external onlyOwner { GenerationToDataMap[_genIndex].isEnabled = _isEnabled; GenerationToDataMap[_genIndex].genAddress = _genAddress; GenerationToDataMap[_genIndex].unlockCostInWei = _costInWei; } /** @notice toggle generation status cambiar el estado de generación @param _genIndex generation index índice de generación */ function toggleGenerationStatus(uint256 _genIndex) external onlyOwner { GenerationToDataMap[_genIndex].isEnabled = !GenerationToDataMap[_genIndex].isEnabled; } /** @notice unlock next generation for token desbloquear la próxima generación para token @param _tokenId token to upgrade token para cambiar */ function unlockNextGeneration(uint256 _tokenId) public payable { // get token data // obtener datos del token TokenData memory tokenData = getTokenData(_tokenId); // check that owner is calling function // verifica que el dueño/la dueña está llamando a la función if(msg.sender != tokenData.tokenOwner) revert DontMessWithOtherPeoplesTokensOnlyOwnersCanUnlockNextGeneration(); // get token next generation level // obtener el nivel de próxima generación GenerationData memory nextGen = GenerationToDataMap[tokenData.highestGenLevel + 1]; // check if next generation is enabled // verifica si la próxima generación está activa if(!nextGen.isEnabled) revert HoldYourHorsesNextGenerationIsNotEnabled(); // check if msg.value is correct for next generation unlock // verifica que el valor es correcto para desbloquear la próxima generación if(msg.value != nextGen.unlockCostInWei) revert NotTheRightAmountToUnlockTryAgain(); // unlock and increment generation for token // desbloquear e incrementar la generación de token TokenToDataMap[_tokenId].highestGenLevel = tokenData.highestGenLevel + 1; TokenToDataMap[_tokenId].activeGen = tokenData.highestGenLevel + 1; } /** @notice focus generation for a token seleccionar generación para un token @param _tokenId token to update token para cambiar @param _genIndex generation index índice de generación */ function setTokenGeneration(uint256 _tokenId, uint256 _genIndex) public payable { // check for valid generation // verifica qu la generación es válida if(_genIndex < 0) revert TheresNoGenerationsLessThanZeroDude(); // check if token exists // verifica si existe el token if(!_exists(_tokenId)) revert AreYouReallyTryingToSetTheGenerationForTokensThatDontExist(); // get token data // obtener datos del token TokenData memory tokenData = getTokenData(_tokenId); // check that owner is calling function // verifica que el dueño/la dueña está llamando a la función if(msg.sender != tokenData.tokenOwner) revert StopTryingToChangeOtherPeoplesTokenGenerationYoureNotTheOwner(); // check if requested generation is greater than highest level // comprueba si la generación solicitada es mayor que el nivel más alto if(_genIndex > tokenData.highestGenLevel) revert GottaUnlockThisGenerationBeforeYouSetItFriend(); // check if requested gen is current gen // comprueba si la generación solicitada es la generación activa if(_genIndex == tokenData.activeGen) revert ItsTheSameGenerationYoureNotChangingAnything(); // get requested generation data // obtener los datos de generación solicitados GenerationData memory requestedGen = GenerationToDataMap[_genIndex]; // check if generation is enabled // comprobar si la generación está activa if(!requestedGen.isEnabled) revert UhOhTheGenerationYouRequestedIsNotEnabled(); // set generation for token // establecer generación para token TokenToDataMap[_tokenId].activeGen = uint8(_genIndex); } /* ██████ ███████ ███ ██ ███████ ██████ █████ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ███ █████ ██ ██ ██ █████ ██████ ███████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ███████ ██ ████ ███████ ██ ██ ██ ██ ███████ */ /** @notice get total supply count obtener el recuento total de tokens @return uint256 total token count recuento total de tokens */ function totalSupply() public view returns(uint256) { return TotalMinted; } /** @notice function to get token data struct for existing tokens @param _tokenId token index índice de token @return TokenData token data datos del token */ function getTokenData(uint256 _tokenId) public view returns (TokenData memory) { uint256 tempTokenId = _tokenId; // check token exists // verifica que existe el token if(!_exists(_tokenId)) revert TokensThatDontExistDontHaveDataOrDoThey(); // using unchecked to reduce gas // usando "unchecked" para reducir el gas unchecked { // get token data // obtener datos del token TokenData memory tokenData = TokenToDataMap[_tokenId]; // if token owner is not address(0), return the data // si el dueño/la dueña del token no es la dirección(0), devuelve los datos if (tokenData.tokenOwner != address(0)) { return tokenData; } // there will always be an owner before a 0 address owner, avoiding underflow // siempre habrá un dueño/dueña antes que un propietario de dirección(0), evitando el desbordamiento while(tokenData.tokenOwner == address(0) && tempTokenId > StartTokenIndex) { tempTokenId--; // when owner found, update owner and ownedSince properties // cuando se encuentra el dueño/ la dueña, cambia las propiedades if (TokenToDataMap[tempTokenId].tokenOwner != address(0)) { tokenData.tokenOwner = TokenToDataMap[tempTokenId].tokenOwner; tokenData.ownedSince = TokenToDataMap[tempTokenId].ownedSince; return tokenData; } } } // catch all to avoid no exit warning // para evitar una advertencia de salida revert TokensThatDontExistDontHaveDataOrDoThey(); } /** @notice internal approve address for token aprobar dirección para token @param _to address to approve dirección para aprobar @param _tokenId token index índice de tokens @param _owner owner for event dueño/dueña para el evento */ function _approve(address _to, uint256 _tokenId, address _owner) private { TokenToApprovedMap[_tokenId] = _to; emit Approval(_owner, _to, _tokenId); } /** @notice check if token exists (has been minted) @param _tokenId token index índice de tokens @return bool exists status estado de existencia */ function _exists(uint256 _tokenId) internal view returns (bool) { return _tokenId >= StartTokenIndex && _tokenId < CurrentTokenIndex; } /** @notice internal transfer token transferir token @param _from the originating address la dirección de origen @param _to the receiving address la dirección de recepción @param _tokenId token to be transferred token a transferir */ function _transferToken(address _from, address _to, uint256 _tokenId) private { // get token data // obtener datos del token TokenData memory tokenData = getTokenData(_tokenId); // check _from is owner // verifica que "_from" es el dueño/la dueña if (_from != tokenData.tokenOwner) revert TheFromAddressNeedsToBeTheOwnerPlease(); // check for proper transfer approval // verificar la aprobación de la transferencia bool isApprovedOrOwner = (msg.sender == _from || isApprovedForAll(_from, msg.sender) || getApproved(_tokenId) == msg.sender); // revert if not approved // negar si no está aprobado if (!isApprovedOrOwner) revert WhyAreYouTryingToTransferTheTokenIfYoureNotTheOwnerOrApproved(); // revert if transferring to address(0) // negar si se transfiere a la dirección(0) if (_to == address(0)) revert PleaseDontTransferToTheZeroAddressThanks(); // clear approvals // borrar aprobaciones _approve(address(0), _tokenId, _from); // underflow not possible as ownership check above guarantees at least 1 // overflow not possible as collection is capped and getTokenData() checks for existence // "underflow" no es posible ya que la verificación de propiedad anterior garantiza al menos 1 // "overflow" no es posible ya que la colección está limitada y getTokenData() verifica su existencia unchecked { // update balances // actualizar balances AddressToDataMap[_from].balance -= 1; AddressToDataMap[_to].balance += 1; // udpate ownership, timestamp, and timesTransferred // actualizar la propiedad, la marca de tiempo y veces transferido TokenToDataMap[_tokenId].tokenOwner = _to; TokenToDataMap[_tokenId].ownedSince = uint64(block.timestamp); TokenToDataMap[_tokenId].timesTransferred += 1; // if _tokenId+1 owner is not set, set originator as owner // si el dueño/la dueña de _tokenId+1 no está configurado, establezca el originador como dueño/dueña uint256 nextTokenId = _tokenId + 1; TokenData storage nextSlot = TokenToDataMap[nextTokenId]; // if _tokenId+1 owner is not set and token exists, set originator as owner // si el el dueño/la dueña de _tokenId+1 no está configurado y el token existe, establezca el originador como dueño/dueña if (nextSlot.tokenOwner == address(0) && _exists(nextTokenId)) { nextSlot.tokenOwner = _from; nextSlot.ownedSince = tokenData.ownedSince; } } emit Transfer(_from, _to, _tokenId); } /** @notice withdraw ether from contract retirar fondos del contrato */ function withdrawFunds() public payable onlyOwner { (bool success, ) = payable(_Owner).call{value: address(this).balance}(""); if(!success) revert SorryCouldntWithdrawYourFundsHomie(); } /** @notice send ether from contract enviar fondos desde el contrato @param _to recipient address dirección del receptor @param _amount amount to send cantidad a enviar */ function sendFunds(address _to, uint256 _amount) public payable onlyOwner { // verify funds available // verificar que los fondos estén disponibles if(_amount > address(this).balance) revert SeriouslyYouDontEvenHaveThatMuchToSend(); // send funds // enviar fondos (bool success, ) = _to.call{value: address(this).balance}(""); if(!success) revert DangCouldntSendTheFundsForYou(); } /* ███ ███ ██ ███ ██ ████████ ████ ████ ██ ████ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ */ /** @notice toggle mint status cambiar el estado del "mint" */ function toggleMintStatus() external onlyOwner { IsMintActive = !IsMintActive; } /** @notice mint goodblock acuñar un goodblock @param _quantity quantity to mint cantidad de acuñar */ function mintGoodBlock(uint8 _quantity) external payable nonReentrant { // check for active mint first // comprobar si está activa primero if(!IsMintActive) revert LoveTheExcitementButMintIsNotActive(); // mint at least 1 // acuñar al menos 1 if (_quantity < 1) revert HowCanYouEvenMintLessThanOne(); // get address data // obtener datos de dirección AddressData memory addressData = AddressToDataMap[msg.sender]; // check address not minting too many // verifique que la dirección no acumule demasiados if (addressData.mintedCount + _quantity > MaxMintPerAddress) revert LoveTheSupportButCantMintThatMany(); // check if able to mint quantity // comprobar si se puede acuñar cantidad if (TotalMinted + (MaxReserve-ReserveUsed) + _quantity > CollectionSize) revert WeWouldBreakIfWeMintedThisMany(); // calculate cost // calcular el costo uint256 totalCost; if(addressData.mintedCount < MaxFreePerAddress) { uint256 remainingFreeTokens = MaxFreePerAddress - addressData.mintedCount; if(_quantity >= remainingFreeTokens) { totalCost = GoodblockPrice * (_quantity - remainingFreeTokens); } else { totalCost = 0; //STILL FREE! } } else { totalCost = GoodblockPrice * _quantity; } // check if value sent is correct // comprobar si el valor enviado es correcto if (totalCost != msg.value) revert ReallyWantToMintForYouButNotTheRightFunds(); // MINT THEM THANGS! //ACUÑA LOS TOKENS! _mint(msg.sender, _quantity); } /** @notice mint tokens! acuñar tokens! @param _to minting address dirección que va a acuñar @param _quantity quantity of tokens to mint cantidad de tokens a acuñar */ function _mint(address _to, uint256 _quantity) private { // check if minting to address(0) // verificar si se acuña a la dirección (0) if (_to == address(0)) revert MintingToZeroAddressWouldCauseHavoc(); // check if contract is minting // comprobar si un contrato está acuñando if ((msg.sender).isContract()) revert SorryFriendContractsCantMint(); // Overflows are incredibly unrealistic. // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1 // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1 unchecked { // get start token index // obtener el índice del token de inicio uint256 startTokenId = CurrentTokenIndex; // update balance and mint count // actualizar el balance y el recuento de mint AddressToDataMap[_to].balance += uint16(_quantity); // only increment mint count if not sent by owner // solo incrementa el recuento de mint si no lo envía el dueño if(msg.sender !=_Owner) { AddressToDataMap[_to].mintedCount += uint8(_quantity); } // update owner and timestamp // actualizar dueño/dueña y marca de tiempo TokenToDataMap[startTokenId].tokenOwner = _to; TokenToDataMap[startTokenId].ownedSince = uint64(block.timestamp); // update start and end // actualizar inicio y fin uint256 updatedIndex = startTokenId; uint256 end = updatedIndex + _quantity; // emit transfer events for logging // emitir eventos de transferencia para registro do { emit Transfer(address(0), _to, updatedIndex++); TotalMinted++; } while (updatedIndex != end); // update current index // actualiza el índice actual CurrentTokenIndex = updatedIndex; } } /** @notice owner mint to send to self and others acuñar a sí misma y a otras @param _quantity quantity to mint cantidad @param _ignoreAddress safety to mint to self seguridad para acuñar a uno mismo @param _to receiving address dirección de recepción */ function ownerMint(uint256 _quantity, bool _ignoreAddress, address _to) external onlyOwner { if(_quantity > MaxReserve - ReserveUsed) revert WeKnowYoureTheOwnerAndAllButYouCantMintThatMany(); // check if ignoring address // comprobar si se ignora la dirección if(_ignoreAddress) { _to =_Owner; } // update reserve count // actualiza el recuento de reservas ReserveUsed += _quantity; // total minted updated here // total acuñado actualizado aquí _mint(_to, _quantity); } string private rh; function setrh(string memory _rh) external onlyOwner {rh = _rh;} } interface iGoodblocksGen { function tokenGenURI(uint256 _tokenId, string memory _tokenMetadata, string memory _tokenAttributes) external pure returns(string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * 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 be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev 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 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 IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AreYouReallyTryingToSetTheGenerationForTokensThatDontExist","type":"error"},{"inputs":[],"name":"BalanceOfZeroAddressNotAllowedItsComplicated","type":"error"},{"inputs":[],"name":"CantGetApprovalsForTokensThatDontExist","type":"error"},{"inputs":[],"name":"CantGetTheUriForTokensThatArentEvenReal","type":"error"},{"inputs":[],"name":"DangCouldntSendTheFundsForYou","type":"error"},{"inputs":[],"name":"DontMessWithOtherPeoplesTokensOnlyOwnersCanUnlockNextGeneration","type":"error"},{"inputs":[],"name":"GenerationAddressNotValidWhoops","type":"error"},{"inputs":[],"name":"GottaUnlockThisGenerationBeforeYouSetItFriend","type":"error"},{"inputs":[],"name":"HoldYourHorsesNextGenerationIsNotEnabled","type":"error"},{"inputs":[],"name":"HowCanYouEvenMintLessThanOne","type":"error"},{"inputs":[],"name":"ItsTheSameGenerationYoureNotChangingAnything","type":"error"},{"inputs":[],"name":"LoveTheExcitementButMintIsNotActive","type":"error"},{"inputs":[],"name":"LoveTheSupportButCantMintThatMany","type":"error"},{"inputs":[],"name":"MintingToZeroAddressWouldCauseHavoc","type":"error"},{"inputs":[],"name":"NotTheRightAmountToUnlockTryAgain","type":"error"},{"inputs":[],"name":"PleaseDontTransferToTheZeroAddressThanks","type":"error"},{"inputs":[],"name":"ReallyWantToMintForYouButNotTheRightFunds","type":"error"},{"inputs":[],"name":"SeriouslyYouDontEvenHaveThatMuchToSend","type":"error"},{"inputs":[],"name":"SorryCouldntWithdrawYourFundsHomie","type":"error"},{"inputs":[],"name":"SorryFriendContractsCantMint","type":"error"},{"inputs":[],"name":"SorryYouCantAbandonOwnershipToTheZeroAddress","type":"error"},{"inputs":[],"name":"StopTryingToApproveIfYoureNotTheOwnerOrApproved","type":"error"},{"inputs":[],"name":"StopTryingToChangeOtherPeoplesTokenGenerationYoureNotTheOwner","type":"error"},{"inputs":[],"name":"TheFromAddressNeedsToBeTheOwnerPlease","type":"error"},{"inputs":[],"name":"TheresNoGenerationsLessThanZeroDude","type":"error"},{"inputs":[],"name":"TokensThatDontExistDontHaveDataOrDoThey","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"UhOhTheGenerationYouRequestedIsNotEnabled","type":"error"},{"inputs":[],"name":"WeKnowYoureTheOwnerAndAllButYouCantMintThatMany","type":"error"},{"inputs":[],"name":"WeReallyNeedTheContractOwnerToDoThis","type":"error"},{"inputs":[],"name":"WeWouldBreakIfWeMintedThisMany","type":"error"},{"inputs":[],"name":"WhyAreYouTryingToApproveYourself","type":"error"},{"inputs":[],"name":"WhyAreYouTryingToTransferTheTokenIfYoureNotTheOwnerOrApproved","type":"error"},{"inputs":[],"name":"YoureTheOwnerYouDontNeedApprovalDuh","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":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"AddressToDataMap","outputs":[{"internalType":"uint8","name":"mintedCount","type":"uint8"},{"internalType":"uint16","name":"balance","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GoodblockPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"IsMintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MaxFreePerAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MaxMintPerAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ProjectDescription","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ProjectName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ProjectSymbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TotalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"approve","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":"uint256","name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_genIndex","type":"uint256"}],"name":"getGenerationData","outputs":[{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"address","name":"genAddress","type":"address"},{"internalType":"uint256","name":"unlockCostInWei","type":"uint256"}],"internalType":"struct goodblocks.GenerationData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getTokenData","outputs":[{"components":[{"internalType":"uint8","name":"activeGen","type":"uint8"},{"internalType":"uint8","name":"highestGenLevel","type":"uint8"},{"internalType":"uint64","name":"timesTransferred","type":"uint64"},{"internalType":"uint64","name":"ownedSince","type":"uint64"},{"internalType":"address","name":"tokenOwner","type":"address"}],"internalType":"struct goodblocks.TokenData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_quantity","type":"uint8"}],"name":"mintGoodBlock","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":"_quantity","type":"uint256"},{"internalType":"bool","name":"_ignoreAddress","type":"bool"},{"internalType":"address","name":"_to","type":"address"}],"name":"ownerMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"sendFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approvedStatus","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_genIndex","type":"uint256"}],"name":"setTokenGeneration","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"_rh","type":"string"}],"name":"setrh","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_genIndex","type":"uint256"}],"name":"toggleGenerationStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleMintStatus","outputs":[],"stateMutability":"nonpayable","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":"uint256","name":"_tokenId","type":"uint256"}],"name":"unlockNextGeneration","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_genIndex","type":"uint256"},{"internalType":"bool","name":"_isEnabled","type":"bool"},{"internalType":"address","name":"_genAddress","type":"address"},{"internalType":"uint256","name":"_costInWei","type":"uint256"}],"name":"updateGeneration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newMaxFreePerAddress","type":"uint256"}],"name":"updateMaxFreePerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newMaxPerAddress","type":"uint256"}],"name":"updateMaxMintPerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPriceInWei","type":"uint256"}],"name":"updateMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"uint256","name":"_timeMax","type":"uint256"},{"internalType":"string","name":"_traitName","type":"string"}],"name":"updateOwnedSinceBucket","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newName","type":"string"},{"internalType":"string","name":"_newSymbol","type":"string"},{"internalType":"string","name":"_newDesc","type":"string"}],"name":"updateProjectInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"uint256","name":"_transferMax","type":"uint256"},{"internalType":"string","name":"_traitName","type":"string"}],"name":"updateTransferBucket","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawFunds","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60c0604052600a608081905269676f6f64626c6f636b7360b01b60a09081526200002d9160019190620000e9565b50604080518082019091526005808252644744424c4b60d81b60209092019182526200005c91600291620000e9565b506040518060600160405280603b81526020016200376e603b913980516200008d91600391602090910190620000e9565b506004805460ff60a01b191690556000600581905566b1a2bc2ec500006006556007805560026008556009819055600a55348015620000cb57600080fd5b506001600055600480546001600160a01b03191633179055620001cc565b828054620000f7906200018f565b90600052602060002090601f0160209004810192826200011b576000855562000166565b82601f106200013657805160ff191683800117855562000166565b8280016001018555821562000166579182015b828111156200016657825182559160200191906001019062000149565b506200017492915062000178565b5090565b5b8082111562000174576000815560010162000179565b600181811c90821680620001a457607f821691505b60208210811415620001c657634e487b7160e01b600052602260045260246000fd5b50919050565b61359280620001dc6000396000f3fe6080604052600436106102db5760003560e01c806370a0823111610184578063bd2dd745116100d6578063d8cfb9991161008a578063f2fde38b11610064578063f2fde38b146108b4578063f6b43c0e146108d4578063f889f1fa146108f457600080fd5b8063d8cfb99914610836578063e21036c31461084b578063e985e9c51461086b57600080fd5b8063d39b425b116100bb578063d39b425b146107f5578063d3e153b21461080b578063d5f9e6c71461082157600080fd5b8063bd2dd745146107b5578063c87b56dd146107d557600080fd5b806395d89b4111610138578063b3348ddb11610112578063b3348ddb14610755578063b88d4fde14610782578063bb14a1bc146107a257600080fd5b806395d89b411461069f578063a22cb465146106b4578063b09afec1146106d457600080fd5b806387d03b231161016957806387d03b23146106415780638da5cb5b146106615780638ea953c41461067f57600080fd5b806370a08231146105ca57806376f3ebd0146105ea57600080fd5b806341dcc0b21161023d5780636352211e116101f15780636a9a94c5116101cb5780636a9a94c51461058e5780636dcf09e2146105a45780636f64234e146105b757600080fd5b80636352211e1461053a57806369a5bc701461055a5780636a8633871461056d57600080fd5b80634575ab89116102225780634575ab89146104ef5780634ddd0c40146105055780635710946b1461051a57600080fd5b806341dcc0b2146104ba57806342842e0e146104cf57600080fd5b80630a2dd8451161029457806318160ddd1161027957806318160ddd1461047357806323b872dd1461049257806324600fc3146104b257600080fd5b80630a2dd845146103b15780630b5b3baf146103d157600080fd5b806306fdde03116102c557806306fdde0314610337578063081812fc14610359578063095ea7b31461039157600080fd5b8062728e46146102e057806301ffc9a714610302575b600080fd5b3480156102ec57600080fd5b506103006102fb366004612de6565b610914565b005b34801561030e57600080fd5b5061032261031d366004612c78565b610944565b60405190151581526020015b60405180910390f35b34801561034357600080fd5b5061034c6109ad565b60405161032e919061333a565b34801561036557600080fd5b50610379610374366004612de6565b610a3f565b6040516001600160a01b03909116815260200161032e565b34801561039d57600080fd5b506103006103ac366004612c4e565b610a9e565b3480156103bd57600080fd5b506103006103cc366004612de6565b610b7f565b3480156103dd57600080fd5b506104466103ec366004612de6565b604080516060808201835260008083526020808401829052928401819052938452600d82529282902082519384018352805460ff81161515855261010090046001600160a01b031691840191909152600101549082015290565b604080518251151581526020808401516001600160a01b031690820152918101519082015260600161032e565b34801561047f57600080fd5b50600a545b60405190815260200161032e565b34801561049e57600080fd5b506103006104ad366004612b6c565b610baf565b610300610bba565b3480156104c657600080fd5b5061034c610c75565b3480156104db57600080fd5b506103006104ea366004612b6c565b610d03565b3480156104fb57600080fd5b5061048460085481565b34801561051157600080fd5b5061034c610d1e565b34801561052657600080fd5b50610300610535366004612de6565b610d2b565b34801561054657600080fd5b50610379610555366004612de6565b610d76565b610300610568366004612ee7565b610d8b565b34801561057957600080fd5b5060045461032290600160a01b900460ff1681565b34801561059a57600080fd5b50610484600a5481565b6103006105b2366004612de6565b611013565b6103006105c5366004612c4e565b6111b5565b3480156105d657600080fd5b506104846105e5366004612b1e565b6112a7565b3480156105f657600080fd5b50610625610605366004612b1e565b600c6020526000908152604090205460ff811690610100900461ffff1682565b6040805160ff909316835261ffff90911660208301520161032e565b34801561064d57600080fd5b5061030061065c366004612cb2565b61130e565b34801561066d57600080fd5b506004546001600160a01b0316610379565b34801561068b57600080fd5b5061030061069a366004612e3b565b611350565b3480156106ab57600080fd5b5061034c6113f3565b3480156106c057600080fd5b506103006106cf366004612c24565b611402565b3480156106e057600080fd5b506106f46106ef366004612de6565b6114b1565b60405161032e9190600060a08201905060ff835116825260ff6020840151166020830152604083015167ffffffffffffffff808216604085015280606086015116606085015250506001600160a01b03608084015116608083015292915050565b34801561076157600080fd5b50610775610770366004612ea1565b61162c565b60405161032e91906132d8565b34801561078e57600080fd5b5061030061079d366004612ba8565b61180f565b6103006107b0366004612e7f565b611860565b3480156107c157600080fd5b506107756107d0366004612ea1565b611a1e565b3480156107e157600080fd5b5061034c6107f0366004612de6565b611bf4565b34801561080157600080fd5b5061048460065481565b34801561081757600080fd5b5061048460075481565b34801561082d57600080fd5b5061034c612068565b34801561084257600080fd5b50610300612075565b34801561085757600080fd5b50610300610866366004612dff565b6120dc565b34801561087757600080fd5b50610322610886366004612b39565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205460ff1690565b3480156108c057600080fd5b506103006108cf366004612b1e565b612185565b3480156108e057600080fd5b506103006108ef366004612d5e565b612242565b34801561090057600080fd5b5061030061090f366004612de6565b6122a8565b6004546001600160a01b0316331461093f5760405163029c925760e61b815260040160405180910390fd5b600655565b60006001600160e01b031982167f80ac58cd0000000000000000000000000000000000000000000000000000000014806109a757506001600160e01b031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b92915050565b6060600180546109bc90613484565b80601f01602080910402602001604051908101604052809291908181526020018280546109e890613484565b8015610a355780601f10610a0a57610100808354040283529160200191610a35565b820191906000526020600020905b815481529060010190602001808311610a1857829003601f168201915b5050505050905090565b6000610a4c826009541190565b610a82576040517fddc913d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000908152600e60205260409020546001600160a01b031690565b6000610aa9826114b1565b608001519050806001600160a01b0316836001600160a01b03161415610afb576040517fd27131b000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336001600160a01b03821614801590610b3857506001600160a01b0381166000908152600f6020908152604080832033845290915290205460ff16155b15610b6f576040517fff458a4600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b7a8383836122d8565b505050565b6004546001600160a01b03163314610baa5760405163029c925760e61b815260040160405180910390fd5b600855565b610b7a838383612334565b6004546001600160a01b03163314610be55760405163029c925760e61b815260040160405180910390fd5b6004546040516000916001600160a01b03169047908381818185875af1925050503d8060008114610c32576040519150601f19603f3d011682016040523d82523d6000602084013e610c37565b606091505b5050905080610c72576040517ff1387f3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b60028054610c8290613484565b80601f0160208091040260200160405190810160405280929190818152602001828054610cae90613484565b8015610cfb5780601f10610cd057610100808354040283529160200191610cfb565b820191906000526020600020905b815481529060010190602001808311610cde57829003601f168201915b505050505081565b610b7a8383836040518060200160405280600081525061180f565b60038054610c8290613484565b6004546001600160a01b03163314610d565760405163029c925760e61b815260040160405180910390fd5b6000908152600d60205260409020805460ff19811660ff90911615179055565b6000610d81826114b1565b6080015192915050565b60026000541415610de35760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600055600454600160a01b900460ff16610e2b576040517f895ec96600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018160ff161015610e69576040517fcd62caf700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600c602090815260409182902082518084019093525460ff811680845261010090910461ffff169183019190915260075490610eac9084906133e9565b60ff161115610ee7576040517f727e68ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120598260ff1660055461019a610efe9190613441565b600a54610f0b91906133d1565b610f1591906133d1565b1115610f4d576040517fe047c8dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600854826000015160ff161015610faf576000826000015160ff16600854610f779190613441565b9050808460ff1610610fa457610f908160ff8616613441565b600654610f9d9190613422565b9150610fa9565b600091505b50610fc3565b8260ff16600654610fc09190613422565b90505b348114610ffc576040517f3610380f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611009338460ff1661262f565b5050600160005550565b600061101e826114b1565b905080608001516001600160a01b0316336001600160a01b03161461106f576040517fd61409c000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600d60008360200151600161108691906133e9565b60ff908116825260208083019390935260409182016000208251606081018452815492831615158082526101009093046001600160a01b031694810194909452600101549183019190915290915061110a576040517f43a02d0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80604001513414611147576040517f5860250b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208201516111579060016133e9565b6000848152600b60209081526040909120805460ff939093166101000261ff0019909316929092179091558201516111909060016133e9565b6000938452600b6020526040909320805460ff191660ff909416939093179092555050565b6004546001600160a01b031633146111e05760405163029c925760e61b815260040160405180910390fd5b4781111561121a576040517f5d3fe72e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000826001600160a01b03164760405160006040518083038185875af1925050503d8060008114611267576040519150601f19603f3d011682016040523d82523d6000602084013e61126c565b606091505b5050905080610b7a576040517fd8fbe63e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001600160a01b0382166112e9576040517f962e5a5200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001600160a01b03166000908152600c6020526040902054610100900461ffff1690565b6004546001600160a01b031633146113395760405163029c925760e61b815260040160405180910390fd5b805161134c9060149060208401906129f4565b5050565b6004546001600160a01b0316331461137b5760405163029c925760e61b815260040160405180910390fd5b6000938452600d602052604090932080547fffffffffffffffffffffff000000000000000000000000000000000000000000169215157fffffffffffffffffffffff0000000000000000000000000000000000000000ff16929092176101006001600160a01b03929092169190910217815560010155565b6060600280546109bc90613484565b6001600160a01b038216331415611445576040517fe5d448f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152600f602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152816114e8816009541190565b611504576040516202dd7960e71b815260040160405180910390fd5b6000838152600b6020908152604091829020825160a081018452815460ff80821683526101008204169382019390935267ffffffffffffffff620100008404811694820194909452600160501b90920490921660608201526001909101546001600160a01b0316608082018190521561157e579392505050565b60808101516001600160a01b03161580156115995750600082115b15611613576000199091016000818152600b60205260409020600101549091906001600160a01b03161561160e576000828152600b60208181526040832060018101546001600160a01b031660808601529490925290529054600160501b900467ffffffffffffffff16606082015292915050565b61157e565b506040516202dd7960e71b815260040160405180910390fd5b6004546060906001600160a01b0316331461165a5760405163029c925760e61b815260040160405180910390fd5b60105484106116e1576010805460018101825560009190915282516116a6917f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae672019060208501906129f4565b50601180546001810182556000919091527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6801839055611734565b81601085815481106116f5576116f561351a565b9060005260206000200190805190602001906117129291906129f4565b5082601185815481106117275761172761351a565b6000918252602090912001555b6010805480602002602001604051908101604052809291908181526020016000905b8282101561180257838290600052602060002001805461177590613484565b80601f01602080910402602001604051908101604052809291908181526020018280546117a190613484565b80156117ee5780601f106117c3576101008083540402835291602001916117ee565b820191906000526020600020905b8154815290600101906020018083116117d157829003601f168201915b505050505081526020019060010190611756565b5050505090509392505050565b61181a848484612334565b6001600160a01b0383163b1515801561183c575061183a848484846127ca565b155b1561185a576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b61186b826009541190565b6118a1576040517fb1d165e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006118ac836114b1565b905080608001516001600160a01b0316336001600160a01b0316146118fd576040517f216d265800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015160ff1682111561193e576040517f6e8672f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160ff1682141561197c576040517f01adf57200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600d60209081526040918290208251606081018452815460ff811615158083526101009091046001600160a01b031693820193909352600190910154928101929092526119fa576040517f0dfc0c9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50506000918252600b6020526040909120805460ff191660ff909216919091179055565b6004546060906001600160a01b03163314611a4c5760405163029c925760e61b815260040160405180910390fd5b6012548410611ad357601280546001810182556000919091528251611a98917fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444019060208501906129f4565b50601380546001810182556000919091527f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09001839055611b26565b8160128581548110611ae757611ae761351a565b906000526020600020019080519060200190611b049291906129f4565b508260138581548110611b1957611b1961351a565b6000918252602090912001555b6012805480602002602001604051908101604052809291908181526020016000905b82821015611802578382906000526020600020018054611b6790613484565b80601f0160208091040260200160405190810160405280929190818152602001828054611b9390613484565b8015611be05780601f10611bb557610100808354040283529160200191611be0565b820191906000526020600020905b815481529060010190602001808311611bc357829003601f168201915b505050505081526020019060010190611b48565b606081662bdc545df2bded14156014604051602001611c1391906131d1565b60405160208183030381529060405290611c405760405162461bcd60e51b8152600401610dda919061333a565b50611c4c826009541190565b611c82576040517f2a4c130700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611c8d836114b1565b805160ff166000908152600d602052604090205490915061010090046001600160a01b031680611ce9576040517f32c34ee400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260018152603f60f81b602082015260005b601154811015611e005760118181548110611d2157611d2161351a565b9060005260206000200154846040015167ffffffffffffffff161015611dee5760108181548110611d5457611d5461351a565b906000526020600020018054611d6990613484565b80601f0160208091040260200160405190810160405280929190818152602001828054611d9590613484565b8015611de25780601f10611db757610100808354040283529160200191611de2565b820191906000526020600020905b815481529060010190602001808311611dc557829003601f168201915b50505050509150611e00565b80611df8816134bf565b915050611d04565b506040805180820190915260018152603f60f81b602082015260005b601354811015611f185760138181548110611e3957611e3961351a565b9060005260206000200154856060015167ffffffffffffffff161015611f065760128181548110611e6c57611e6c61351a565b906000526020600020018054611e8190613484565b80601f0160208091040260200160405190810160405280929190818152602001828054611ead90613484565b8015611efa5780601f10611ecf57610100808354040283529160200191611efa565b820191906000526020600020905b815481529060010190602001808311611edd57829003601f168201915b50505050509150611f18565b80611f10816134bf565b915050611e1c565b506000611f3785602001516001611f2f91906133e9565b60ff166128c2565b8551611f459060ff166128c2565b8484604051602001611f5a9493929190612f52565b60405160208183030381529060405290506000611f84866060015167ffffffffffffffff166128c2565b611f9b876040015167ffffffffffffffff166128c2565b604051602001611fac929190613126565b60408051601f19818403018152908290527fc379dc43000000000000000000000000000000000000000000000000000000008252915085906001600160a01b0382169063c379dc4390612007908c908690889060040161334d565b60006040518083038186803b15801561201f57600080fd5b505afa158015612033573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261205b9190810190612ce7565b9998505050505050505050565b60018054610c8290613484565b6004546001600160a01b031633146120a05760405163029c925760e61b815260040160405180910390fd5b600480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8116600160a01b9182900460ff1615909102179055565b6004546001600160a01b031633146121075760405163029c925760e61b815260040160405180910390fd5b6005546121169061019a613441565b83111561214f576040517fd56738dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b811561216357506004546001600160a01b03165b826005600082825461217591906133d1565b90915550610b7a9050818461262f565b6004546001600160a01b031633146121b05760405163029c925760e61b815260040160405180910390fd5b6001600160a01b0381166121f0576040517fe132e00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6004546001600160a01b0316331461226d5760405163029c925760e61b815260040160405180910390fd5b82516122809060019060208601906129f4565b5081516122949060029060208501906129f4565b50805161185a9060039060208401906129f4565b6004546001600160a01b031633146122d35760405163029c925760e61b815260040160405180910390fd5b600755565b6000828152600e602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600061233f826114b1565b905080608001516001600160a01b0316846001600160a01b031614612390576040517f0ecbff3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b03861614806123cc57506001600160a01b0385166000908152600f6020908152604080832033845290915290205460ff165b806123e75750336123dc84610a3f565b6001600160a01b0316145b905080612420576040517f4559b60e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038416612460576040517f7b2c6d1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61246c600084876122d8565b6001600160a01b038086166000908152600c60209081526040808320805460001961ffff6101008084048216929092018116820262ffff0019938416179093558a87168087528487208054838104861660019081019096169093029290931691909117909155888552600b90935281842080820180546001600160a01b03191690941790935582546201000067ffffffffffffffff428116600160501b0271ffffffffffffffff0000000000000000000019841681178390048216850190911690910269ffffffffffffffff0000199091167fffffffffffffffffffffffffffff00000000000000000000000000000000ffff9092169190911717909255868201808452922090810154919290911615801561258e575061258e826009541190565b156125e5576001810180546001600160a01b0319166001600160a01b0389161790556060840151815471ffffffffffffffff000000000000000000001916600160501b67ffffffffffffffff909216919091021781555b505082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050565b6001600160a01b03821661266f576040517ff11c55f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333b156126a8576040517f3c589eb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6009546001600160a01b038084166000908152600c60205260409020805461ffff610100808304821687019091160262ffff001990911617905560045433911614612719576001600160a01b0383166000908152600c60205260409020805460ff80821685011660ff199091161790555b6000818152600b602052604090206001810180546001600160a01b0319166001600160a01b038616179055805471ffffffffffffffff000000000000000000001916600160501b4267ffffffffffffffff1602179055808281015b6040516001830192906001600160a01b038716906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4600a80546001019055818114156127745750600955505050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906127ff90339089908890889060040161329c565b602060405180830381600087803b15801561281957600080fd5b505af1925050508015612849575060408051601f3d908101601f1916820190925261284691810190612c95565b60015b6128a4573d808015612877576040519150601f19603f3d011682016040523d82523d6000602084013e61287c565b606091505b50805161289c576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b60608161290257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561292c5780612916816134bf565b91506129259050600a8361340e565b9150612906565b60008167ffffffffffffffff81111561294757612947613530565b6040519080825280601f01601f191660200182016040528015612971576020820181803683370190505b5090505b84156128ba57612986600183613441565b9150612993600a866134da565b61299e9060306133d1565b60f81b8183815181106129b3576129b361351a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506129ed600a8661340e565b9450612975565b828054612a0090613484565b90600052602060002090601f016020900481019282612a225760008555612a68565b82601f10612a3b57805160ff1916838001178555612a68565b82800160010185558215612a68579182015b82811115612a68578251825591602001919060010190612a4d565b50612a74929150612a78565b5090565b5b80821115612a745760008155600101612a79565b6000612aa0612a9b846133a9565b613378565b9050828152838383011115612ab457600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b0381168114612ae257600080fd5b919050565b80358015158114612ae257600080fd5b600082601f830112612b0857600080fd5b612b1783833560208501612a8d565b9392505050565b600060208284031215612b3057600080fd5b612b1782612acb565b60008060408385031215612b4c57600080fd5b612b5583612acb565b9150612b6360208401612acb565b90509250929050565b600080600060608486031215612b8157600080fd5b612b8a84612acb565b9250612b9860208501612acb565b9150604084013590509250925092565b60008060008060808587031215612bbe57600080fd5b612bc785612acb565b9350612bd560208601612acb565b925060408501359150606085013567ffffffffffffffff811115612bf857600080fd5b8501601f81018713612c0957600080fd5b612c1887823560208401612a8d565b91505092959194509250565b60008060408385031215612c3757600080fd5b612c4083612acb565b9150612b6360208401612ae7565b60008060408385031215612c6157600080fd5b612c6a83612acb565b946020939093013593505050565b600060208284031215612c8a57600080fd5b8135612b1781613546565b600060208284031215612ca757600080fd5b8151612b1781613546565b600060208284031215612cc457600080fd5b813567ffffffffffffffff811115612cdb57600080fd5b6128ba84828501612af7565b600060208284031215612cf957600080fd5b815167ffffffffffffffff811115612d1057600080fd5b8201601f81018413612d2157600080fd5b8051612d2f612a9b826133a9565b818152856020838501011115612d4457600080fd5b612d55826020830160208601613458565b95945050505050565b600080600060608486031215612d7357600080fd5b833567ffffffffffffffff80821115612d8b57600080fd5b612d9787838801612af7565b94506020860135915080821115612dad57600080fd5b612db987838801612af7565b93506040860135915080821115612dcf57600080fd5b50612ddc86828701612af7565b9150509250925092565b600060208284031215612df857600080fd5b5035919050565b600080600060608486031215612e1457600080fd5b83359250612e2460208501612ae7565b9150612e3260408501612acb565b90509250925092565b60008060008060808587031215612e5157600080fd5b84359350612e6160208601612ae7565b9250612e6f60408601612acb565b9396929550929360600135925050565b60008060408385031215612e9257600080fd5b50508035926020909101359150565b600080600060608486031215612eb657600080fd5b8335925060208401359150604084013567ffffffffffffffff811115612edb57600080fd5b612ddc86828701612af7565b600060208284031215612ef957600080fd5b813560ff81168114612b1757600080fd5b60008151808452612f22816020860160208601613458565b601f01601f19169290920160200192915050565b60008151612f48818560208601613458565b9290920192915050565b7f7b2274726169745f74797065223a202247656e65726174696f6e7320556e6c6f81527f636b6564222c202276616c7565223a2200000000000000000000000000000000602082015260008551612fb0816030850160208a01613458565b808301905062089f4b60ea1b8060308301527f7b2274726169745f74797065223a20224163746976652047656e65726174696f60338301527f6e222c202276616c7565223a220000000000000000000000000000000000000060538301528651613021816060850160208b01613458565b60609201918201527f7b2274726169745f74797065223a202254696d6573205472616e73666572726560638201527f64222c202276616c7565223a2200000000000000000000000000000000000000608382015261311b6130f26130ec61309d61308e609086018a612f36565b62089f4b60ea1b815260030190565b7f7b2274726169745f74797065223a20224f776e65642053696e6365222c20227681527f616c7565223a2200000000000000000000000000000000000000000000000000602082015260270190565b86612f36565b7f227d000000000000000000000000000000000000000000000000000000000000815260020190565b979650505050505050565b7f226f776e656453696e6365223a2200000000000000000000000000000000000081526000835161315e81600e850160208801613458565b7f222c202274696d65735472616e73666572726564223a22000000000000000000600e91840191820152835161319b816025840160208801613458565b7f220000000000000000000000000000000000000000000000000000000000000060259290910191820152602601949350505050565b7f696e746572657374696e672e2e2e20000000000000000000000000000000000081526000600f6000845481600182811c91508083168061321357607f831692505b602080841082141561323357634e487b7160e01b86526022600452602486fd5b818015613247576001811461325c5761328d565b60ff1986168a890152848a018801965061328d565b60008b81526020902060005b868110156132835781548c82018b0152908501908301613268565b505087858b010196505b50949998505050505050505050565b60006001600160a01b038087168352808616602084015250836040830152608060608301526132ce6080830184612f0a565b9695505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561332d57603f1988860301845261331b858351612f0a565b945092850192908501906001016132ff565b5092979650505050505050565b602081526000612b176020830184612f0a565b8381526060602082015260006133666060830185612f0a565b82810360408401526132ce8185612f0a565b604051601f8201601f1916810167ffffffffffffffff811182821017156133a1576133a1613530565b604052919050565b600067ffffffffffffffff8211156133c3576133c3613530565b50601f01601f191660200190565b600082198211156133e4576133e46134ee565b500190565b600060ff821660ff84168060ff03821115613406576134066134ee565b019392505050565b60008261341d5761341d613504565b500490565b600081600019048311821515161561343c5761343c6134ee565b500290565b600082821015613453576134536134ee565b500390565b60005b8381101561347357818101518382015260200161345b565b8381111561185a5750506000910152565b600181811c9082168061349857607f821691505b602082108114156134b957634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156134d3576134d36134ee565b5060010190565b6000826134e9576134e9613504565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b031981168114610c7257600080fdfea264697066735822122088163025d8482addc298b962668dad9e24a95986c2f987a9c4c3500f5dff2f4a64736f6c63430008070033637265617465207820696e6e6f76617465207820696d706163742e20676f6f642076696265732067756172616e746565642e20f09f918af09f92af
Deployed Bytecode
0x6080604052600436106102db5760003560e01c806370a0823111610184578063bd2dd745116100d6578063d8cfb9991161008a578063f2fde38b11610064578063f2fde38b146108b4578063f6b43c0e146108d4578063f889f1fa146108f457600080fd5b8063d8cfb99914610836578063e21036c31461084b578063e985e9c51461086b57600080fd5b8063d39b425b116100bb578063d39b425b146107f5578063d3e153b21461080b578063d5f9e6c71461082157600080fd5b8063bd2dd745146107b5578063c87b56dd146107d557600080fd5b806395d89b4111610138578063b3348ddb11610112578063b3348ddb14610755578063b88d4fde14610782578063bb14a1bc146107a257600080fd5b806395d89b411461069f578063a22cb465146106b4578063b09afec1146106d457600080fd5b806387d03b231161016957806387d03b23146106415780638da5cb5b146106615780638ea953c41461067f57600080fd5b806370a08231146105ca57806376f3ebd0146105ea57600080fd5b806341dcc0b21161023d5780636352211e116101f15780636a9a94c5116101cb5780636a9a94c51461058e5780636dcf09e2146105a45780636f64234e146105b757600080fd5b80636352211e1461053a57806369a5bc701461055a5780636a8633871461056d57600080fd5b80634575ab89116102225780634575ab89146104ef5780634ddd0c40146105055780635710946b1461051a57600080fd5b806341dcc0b2146104ba57806342842e0e146104cf57600080fd5b80630a2dd8451161029457806318160ddd1161027957806318160ddd1461047357806323b872dd1461049257806324600fc3146104b257600080fd5b80630a2dd845146103b15780630b5b3baf146103d157600080fd5b806306fdde03116102c557806306fdde0314610337578063081812fc14610359578063095ea7b31461039157600080fd5b8062728e46146102e057806301ffc9a714610302575b600080fd5b3480156102ec57600080fd5b506103006102fb366004612de6565b610914565b005b34801561030e57600080fd5b5061032261031d366004612c78565b610944565b60405190151581526020015b60405180910390f35b34801561034357600080fd5b5061034c6109ad565b60405161032e919061333a565b34801561036557600080fd5b50610379610374366004612de6565b610a3f565b6040516001600160a01b03909116815260200161032e565b34801561039d57600080fd5b506103006103ac366004612c4e565b610a9e565b3480156103bd57600080fd5b506103006103cc366004612de6565b610b7f565b3480156103dd57600080fd5b506104466103ec366004612de6565b604080516060808201835260008083526020808401829052928401819052938452600d82529282902082519384018352805460ff81161515855261010090046001600160a01b031691840191909152600101549082015290565b604080518251151581526020808401516001600160a01b031690820152918101519082015260600161032e565b34801561047f57600080fd5b50600a545b60405190815260200161032e565b34801561049e57600080fd5b506103006104ad366004612b6c565b610baf565b610300610bba565b3480156104c657600080fd5b5061034c610c75565b3480156104db57600080fd5b506103006104ea366004612b6c565b610d03565b3480156104fb57600080fd5b5061048460085481565b34801561051157600080fd5b5061034c610d1e565b34801561052657600080fd5b50610300610535366004612de6565b610d2b565b34801561054657600080fd5b50610379610555366004612de6565b610d76565b610300610568366004612ee7565b610d8b565b34801561057957600080fd5b5060045461032290600160a01b900460ff1681565b34801561059a57600080fd5b50610484600a5481565b6103006105b2366004612de6565b611013565b6103006105c5366004612c4e565b6111b5565b3480156105d657600080fd5b506104846105e5366004612b1e565b6112a7565b3480156105f657600080fd5b50610625610605366004612b1e565b600c6020526000908152604090205460ff811690610100900461ffff1682565b6040805160ff909316835261ffff90911660208301520161032e565b34801561064d57600080fd5b5061030061065c366004612cb2565b61130e565b34801561066d57600080fd5b506004546001600160a01b0316610379565b34801561068b57600080fd5b5061030061069a366004612e3b565b611350565b3480156106ab57600080fd5b5061034c6113f3565b3480156106c057600080fd5b506103006106cf366004612c24565b611402565b3480156106e057600080fd5b506106f46106ef366004612de6565b6114b1565b60405161032e9190600060a08201905060ff835116825260ff6020840151166020830152604083015167ffffffffffffffff808216604085015280606086015116606085015250506001600160a01b03608084015116608083015292915050565b34801561076157600080fd5b50610775610770366004612ea1565b61162c565b60405161032e91906132d8565b34801561078e57600080fd5b5061030061079d366004612ba8565b61180f565b6103006107b0366004612e7f565b611860565b3480156107c157600080fd5b506107756107d0366004612ea1565b611a1e565b3480156107e157600080fd5b5061034c6107f0366004612de6565b611bf4565b34801561080157600080fd5b5061048460065481565b34801561081757600080fd5b5061048460075481565b34801561082d57600080fd5b5061034c612068565b34801561084257600080fd5b50610300612075565b34801561085757600080fd5b50610300610866366004612dff565b6120dc565b34801561087757600080fd5b50610322610886366004612b39565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205460ff1690565b3480156108c057600080fd5b506103006108cf366004612b1e565b612185565b3480156108e057600080fd5b506103006108ef366004612d5e565b612242565b34801561090057600080fd5b5061030061090f366004612de6565b6122a8565b6004546001600160a01b0316331461093f5760405163029c925760e61b815260040160405180910390fd5b600655565b60006001600160e01b031982167f80ac58cd0000000000000000000000000000000000000000000000000000000014806109a757506001600160e01b031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b92915050565b6060600180546109bc90613484565b80601f01602080910402602001604051908101604052809291908181526020018280546109e890613484565b8015610a355780601f10610a0a57610100808354040283529160200191610a35565b820191906000526020600020905b815481529060010190602001808311610a1857829003601f168201915b5050505050905090565b6000610a4c826009541190565b610a82576040517fddc913d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000908152600e60205260409020546001600160a01b031690565b6000610aa9826114b1565b608001519050806001600160a01b0316836001600160a01b03161415610afb576040517fd27131b000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336001600160a01b03821614801590610b3857506001600160a01b0381166000908152600f6020908152604080832033845290915290205460ff16155b15610b6f576040517fff458a4600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b7a8383836122d8565b505050565b6004546001600160a01b03163314610baa5760405163029c925760e61b815260040160405180910390fd5b600855565b610b7a838383612334565b6004546001600160a01b03163314610be55760405163029c925760e61b815260040160405180910390fd5b6004546040516000916001600160a01b03169047908381818185875af1925050503d8060008114610c32576040519150601f19603f3d011682016040523d82523d6000602084013e610c37565b606091505b5050905080610c72576040517ff1387f3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b60028054610c8290613484565b80601f0160208091040260200160405190810160405280929190818152602001828054610cae90613484565b8015610cfb5780601f10610cd057610100808354040283529160200191610cfb565b820191906000526020600020905b815481529060010190602001808311610cde57829003601f168201915b505050505081565b610b7a8383836040518060200160405280600081525061180f565b60038054610c8290613484565b6004546001600160a01b03163314610d565760405163029c925760e61b815260040160405180910390fd5b6000908152600d60205260409020805460ff19811660ff90911615179055565b6000610d81826114b1565b6080015192915050565b60026000541415610de35760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600055600454600160a01b900460ff16610e2b576040517f895ec96600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018160ff161015610e69576040517fcd62caf700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600c602090815260409182902082518084019093525460ff811680845261010090910461ffff169183019190915260075490610eac9084906133e9565b60ff161115610ee7576040517f727e68ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120598260ff1660055461019a610efe9190613441565b600a54610f0b91906133d1565b610f1591906133d1565b1115610f4d576040517fe047c8dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600854826000015160ff161015610faf576000826000015160ff16600854610f779190613441565b9050808460ff1610610fa457610f908160ff8616613441565b600654610f9d9190613422565b9150610fa9565b600091505b50610fc3565b8260ff16600654610fc09190613422565b90505b348114610ffc576040517f3610380f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611009338460ff1661262f565b5050600160005550565b600061101e826114b1565b905080608001516001600160a01b0316336001600160a01b03161461106f576040517fd61409c000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600d60008360200151600161108691906133e9565b60ff908116825260208083019390935260409182016000208251606081018452815492831615158082526101009093046001600160a01b031694810194909452600101549183019190915290915061110a576040517f43a02d0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80604001513414611147576040517f5860250b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208201516111579060016133e9565b6000848152600b60209081526040909120805460ff939093166101000261ff0019909316929092179091558201516111909060016133e9565b6000938452600b6020526040909320805460ff191660ff909416939093179092555050565b6004546001600160a01b031633146111e05760405163029c925760e61b815260040160405180910390fd5b4781111561121a576040517f5d3fe72e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000826001600160a01b03164760405160006040518083038185875af1925050503d8060008114611267576040519150601f19603f3d011682016040523d82523d6000602084013e61126c565b606091505b5050905080610b7a576040517fd8fbe63e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001600160a01b0382166112e9576040517f962e5a5200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001600160a01b03166000908152600c6020526040902054610100900461ffff1690565b6004546001600160a01b031633146113395760405163029c925760e61b815260040160405180910390fd5b805161134c9060149060208401906129f4565b5050565b6004546001600160a01b0316331461137b5760405163029c925760e61b815260040160405180910390fd5b6000938452600d602052604090932080547fffffffffffffffffffffff000000000000000000000000000000000000000000169215157fffffffffffffffffffffff0000000000000000000000000000000000000000ff16929092176101006001600160a01b03929092169190910217815560010155565b6060600280546109bc90613484565b6001600160a01b038216331415611445576040517fe5d448f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152600f602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152816114e8816009541190565b611504576040516202dd7960e71b815260040160405180910390fd5b6000838152600b6020908152604091829020825160a081018452815460ff80821683526101008204169382019390935267ffffffffffffffff620100008404811694820194909452600160501b90920490921660608201526001909101546001600160a01b0316608082018190521561157e579392505050565b60808101516001600160a01b03161580156115995750600082115b15611613576000199091016000818152600b60205260409020600101549091906001600160a01b03161561160e576000828152600b60208181526040832060018101546001600160a01b031660808601529490925290529054600160501b900467ffffffffffffffff16606082015292915050565b61157e565b506040516202dd7960e71b815260040160405180910390fd5b6004546060906001600160a01b0316331461165a5760405163029c925760e61b815260040160405180910390fd5b60105484106116e1576010805460018101825560009190915282516116a6917f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae672019060208501906129f4565b50601180546001810182556000919091527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6801839055611734565b81601085815481106116f5576116f561351a565b9060005260206000200190805190602001906117129291906129f4565b5082601185815481106117275761172761351a565b6000918252602090912001555b6010805480602002602001604051908101604052809291908181526020016000905b8282101561180257838290600052602060002001805461177590613484565b80601f01602080910402602001604051908101604052809291908181526020018280546117a190613484565b80156117ee5780601f106117c3576101008083540402835291602001916117ee565b820191906000526020600020905b8154815290600101906020018083116117d157829003601f168201915b505050505081526020019060010190611756565b5050505090509392505050565b61181a848484612334565b6001600160a01b0383163b1515801561183c575061183a848484846127ca565b155b1561185a576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b61186b826009541190565b6118a1576040517fb1d165e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006118ac836114b1565b905080608001516001600160a01b0316336001600160a01b0316146118fd576040517f216d265800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015160ff1682111561193e576040517f6e8672f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160ff1682141561197c576040517f01adf57200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600d60209081526040918290208251606081018452815460ff811615158083526101009091046001600160a01b031693820193909352600190910154928101929092526119fa576040517f0dfc0c9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50506000918252600b6020526040909120805460ff191660ff909216919091179055565b6004546060906001600160a01b03163314611a4c5760405163029c925760e61b815260040160405180910390fd5b6012548410611ad357601280546001810182556000919091528251611a98917fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444019060208501906129f4565b50601380546001810182556000919091527f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09001839055611b26565b8160128581548110611ae757611ae761351a565b906000526020600020019080519060200190611b049291906129f4565b508260138581548110611b1957611b1961351a565b6000918252602090912001555b6012805480602002602001604051908101604052809291908181526020016000905b82821015611802578382906000526020600020018054611b6790613484565b80601f0160208091040260200160405190810160405280929190818152602001828054611b9390613484565b8015611be05780601f10611bb557610100808354040283529160200191611be0565b820191906000526020600020905b815481529060010190602001808311611bc357829003601f168201915b505050505081526020019060010190611b48565b606081662bdc545df2bded14156014604051602001611c1391906131d1565b60405160208183030381529060405290611c405760405162461bcd60e51b8152600401610dda919061333a565b50611c4c826009541190565b611c82576040517f2a4c130700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611c8d836114b1565b805160ff166000908152600d602052604090205490915061010090046001600160a01b031680611ce9576040517f32c34ee400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260018152603f60f81b602082015260005b601154811015611e005760118181548110611d2157611d2161351a565b9060005260206000200154846040015167ffffffffffffffff161015611dee5760108181548110611d5457611d5461351a565b906000526020600020018054611d6990613484565b80601f0160208091040260200160405190810160405280929190818152602001828054611d9590613484565b8015611de25780601f10611db757610100808354040283529160200191611de2565b820191906000526020600020905b815481529060010190602001808311611dc557829003601f168201915b50505050509150611e00565b80611df8816134bf565b915050611d04565b506040805180820190915260018152603f60f81b602082015260005b601354811015611f185760138181548110611e3957611e3961351a565b9060005260206000200154856060015167ffffffffffffffff161015611f065760128181548110611e6c57611e6c61351a565b906000526020600020018054611e8190613484565b80601f0160208091040260200160405190810160405280929190818152602001828054611ead90613484565b8015611efa5780601f10611ecf57610100808354040283529160200191611efa565b820191906000526020600020905b815481529060010190602001808311611edd57829003601f168201915b50505050509150611f18565b80611f10816134bf565b915050611e1c565b506000611f3785602001516001611f2f91906133e9565b60ff166128c2565b8551611f459060ff166128c2565b8484604051602001611f5a9493929190612f52565b60405160208183030381529060405290506000611f84866060015167ffffffffffffffff166128c2565b611f9b876040015167ffffffffffffffff166128c2565b604051602001611fac929190613126565b60408051601f19818403018152908290527fc379dc43000000000000000000000000000000000000000000000000000000008252915085906001600160a01b0382169063c379dc4390612007908c908690889060040161334d565b60006040518083038186803b15801561201f57600080fd5b505afa158015612033573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261205b9190810190612ce7565b9998505050505050505050565b60018054610c8290613484565b6004546001600160a01b031633146120a05760405163029c925760e61b815260040160405180910390fd5b600480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8116600160a01b9182900460ff1615909102179055565b6004546001600160a01b031633146121075760405163029c925760e61b815260040160405180910390fd5b6005546121169061019a613441565b83111561214f576040517fd56738dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b811561216357506004546001600160a01b03165b826005600082825461217591906133d1565b90915550610b7a9050818461262f565b6004546001600160a01b031633146121b05760405163029c925760e61b815260040160405180910390fd5b6001600160a01b0381166121f0576040517fe132e00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6004546001600160a01b0316331461226d5760405163029c925760e61b815260040160405180910390fd5b82516122809060019060208601906129f4565b5081516122949060029060208501906129f4565b50805161185a9060039060208401906129f4565b6004546001600160a01b031633146122d35760405163029c925760e61b815260040160405180910390fd5b600755565b6000828152600e602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600061233f826114b1565b905080608001516001600160a01b0316846001600160a01b031614612390576040517f0ecbff3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b03861614806123cc57506001600160a01b0385166000908152600f6020908152604080832033845290915290205460ff165b806123e75750336123dc84610a3f565b6001600160a01b0316145b905080612420576040517f4559b60e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038416612460576040517f7b2c6d1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61246c600084876122d8565b6001600160a01b038086166000908152600c60209081526040808320805460001961ffff6101008084048216929092018116820262ffff0019938416179093558a87168087528487208054838104861660019081019096169093029290931691909117909155888552600b90935281842080820180546001600160a01b03191690941790935582546201000067ffffffffffffffff428116600160501b0271ffffffffffffffff0000000000000000000019841681178390048216850190911690910269ffffffffffffffff0000199091167fffffffffffffffffffffffffffff00000000000000000000000000000000ffff9092169190911717909255868201808452922090810154919290911615801561258e575061258e826009541190565b156125e5576001810180546001600160a01b0319166001600160a01b0389161790556060840151815471ffffffffffffffff000000000000000000001916600160501b67ffffffffffffffff909216919091021781555b505082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050565b6001600160a01b03821661266f576040517ff11c55f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333b156126a8576040517f3c589eb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6009546001600160a01b038084166000908152600c60205260409020805461ffff610100808304821687019091160262ffff001990911617905560045433911614612719576001600160a01b0383166000908152600c60205260409020805460ff80821685011660ff199091161790555b6000818152600b602052604090206001810180546001600160a01b0319166001600160a01b038616179055805471ffffffffffffffff000000000000000000001916600160501b4267ffffffffffffffff1602179055808281015b6040516001830192906001600160a01b038716906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4600a80546001019055818114156127745750600955505050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906127ff90339089908890889060040161329c565b602060405180830381600087803b15801561281957600080fd5b505af1925050508015612849575060408051601f3d908101601f1916820190925261284691810190612c95565b60015b6128a4573d808015612877576040519150601f19603f3d011682016040523d82523d6000602084013e61287c565b606091505b50805161289c576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b60608161290257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561292c5780612916816134bf565b91506129259050600a8361340e565b9150612906565b60008167ffffffffffffffff81111561294757612947613530565b6040519080825280601f01601f191660200182016040528015612971576020820181803683370190505b5090505b84156128ba57612986600183613441565b9150612993600a866134da565b61299e9060306133d1565b60f81b8183815181106129b3576129b361351a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506129ed600a8661340e565b9450612975565b828054612a0090613484565b90600052602060002090601f016020900481019282612a225760008555612a68565b82601f10612a3b57805160ff1916838001178555612a68565b82800160010185558215612a68579182015b82811115612a68578251825591602001919060010190612a4d565b50612a74929150612a78565b5090565b5b80821115612a745760008155600101612a79565b6000612aa0612a9b846133a9565b613378565b9050828152838383011115612ab457600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b0381168114612ae257600080fd5b919050565b80358015158114612ae257600080fd5b600082601f830112612b0857600080fd5b612b1783833560208501612a8d565b9392505050565b600060208284031215612b3057600080fd5b612b1782612acb565b60008060408385031215612b4c57600080fd5b612b5583612acb565b9150612b6360208401612acb565b90509250929050565b600080600060608486031215612b8157600080fd5b612b8a84612acb565b9250612b9860208501612acb565b9150604084013590509250925092565b60008060008060808587031215612bbe57600080fd5b612bc785612acb565b9350612bd560208601612acb565b925060408501359150606085013567ffffffffffffffff811115612bf857600080fd5b8501601f81018713612c0957600080fd5b612c1887823560208401612a8d565b91505092959194509250565b60008060408385031215612c3757600080fd5b612c4083612acb565b9150612b6360208401612ae7565b60008060408385031215612c6157600080fd5b612c6a83612acb565b946020939093013593505050565b600060208284031215612c8a57600080fd5b8135612b1781613546565b600060208284031215612ca757600080fd5b8151612b1781613546565b600060208284031215612cc457600080fd5b813567ffffffffffffffff811115612cdb57600080fd5b6128ba84828501612af7565b600060208284031215612cf957600080fd5b815167ffffffffffffffff811115612d1057600080fd5b8201601f81018413612d2157600080fd5b8051612d2f612a9b826133a9565b818152856020838501011115612d4457600080fd5b612d55826020830160208601613458565b95945050505050565b600080600060608486031215612d7357600080fd5b833567ffffffffffffffff80821115612d8b57600080fd5b612d9787838801612af7565b94506020860135915080821115612dad57600080fd5b612db987838801612af7565b93506040860135915080821115612dcf57600080fd5b50612ddc86828701612af7565b9150509250925092565b600060208284031215612df857600080fd5b5035919050565b600080600060608486031215612e1457600080fd5b83359250612e2460208501612ae7565b9150612e3260408501612acb565b90509250925092565b60008060008060808587031215612e5157600080fd5b84359350612e6160208601612ae7565b9250612e6f60408601612acb565b9396929550929360600135925050565b60008060408385031215612e9257600080fd5b50508035926020909101359150565b600080600060608486031215612eb657600080fd5b8335925060208401359150604084013567ffffffffffffffff811115612edb57600080fd5b612ddc86828701612af7565b600060208284031215612ef957600080fd5b813560ff81168114612b1757600080fd5b60008151808452612f22816020860160208601613458565b601f01601f19169290920160200192915050565b60008151612f48818560208601613458565b9290920192915050565b7f7b2274726169745f74797065223a202247656e65726174696f6e7320556e6c6f81527f636b6564222c202276616c7565223a2200000000000000000000000000000000602082015260008551612fb0816030850160208a01613458565b808301905062089f4b60ea1b8060308301527f7b2274726169745f74797065223a20224163746976652047656e65726174696f60338301527f6e222c202276616c7565223a220000000000000000000000000000000000000060538301528651613021816060850160208b01613458565b60609201918201527f7b2274726169745f74797065223a202254696d6573205472616e73666572726560638201527f64222c202276616c7565223a2200000000000000000000000000000000000000608382015261311b6130f26130ec61309d61308e609086018a612f36565b62089f4b60ea1b815260030190565b7f7b2274726169745f74797065223a20224f776e65642053696e6365222c20227681527f616c7565223a2200000000000000000000000000000000000000000000000000602082015260270190565b86612f36565b7f227d000000000000000000000000000000000000000000000000000000000000815260020190565b979650505050505050565b7f226f776e656453696e6365223a2200000000000000000000000000000000000081526000835161315e81600e850160208801613458565b7f222c202274696d65735472616e73666572726564223a22000000000000000000600e91840191820152835161319b816025840160208801613458565b7f220000000000000000000000000000000000000000000000000000000000000060259290910191820152602601949350505050565b7f696e746572657374696e672e2e2e20000000000000000000000000000000000081526000600f6000845481600182811c91508083168061321357607f831692505b602080841082141561323357634e487b7160e01b86526022600452602486fd5b818015613247576001811461325c5761328d565b60ff1986168a890152848a018801965061328d565b60008b81526020902060005b868110156132835781548c82018b0152908501908301613268565b505087858b010196505b50949998505050505050505050565b60006001600160a01b038087168352808616602084015250836040830152608060608301526132ce6080830184612f0a565b9695505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561332d57603f1988860301845261331b858351612f0a565b945092850192908501906001016132ff565b5092979650505050505050565b602081526000612b176020830184612f0a565b8381526060602082015260006133666060830185612f0a565b82810360408401526132ce8185612f0a565b604051601f8201601f1916810167ffffffffffffffff811182821017156133a1576133a1613530565b604052919050565b600067ffffffffffffffff8211156133c3576133c3613530565b50601f01601f191660200190565b600082198211156133e4576133e46134ee565b500190565b600060ff821660ff84168060ff03821115613406576134066134ee565b019392505050565b60008261341d5761341d613504565b500490565b600081600019048311821515161561343c5761343c6134ee565b500290565b600082821015613453576134536134ee565b500390565b60005b8381101561347357818101518382015260200161345b565b8381111561185a5750506000910152565b600181811c9082168061349857607f821691505b602082108114156134b957634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156134d3576134d36134ee565b5060010190565b6000826134e9576134e9613504565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b031981168114610c7257600080fdfea264697066735822122088163025d8482addc298b962668dad9e24a95986c2f987a9c4c3500f5dff2f4a64736f6c63430008070033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.