Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 76 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Approval For... | 17608594 | 522 days ago | IN | 0 ETH | 0.00075524 | ||||
Set Approval For... | 16777602 | 639 days ago | IN | 0 ETH | 0.00232883 | ||||
Set Approval For... | 16599559 | 664 days ago | IN | 0 ETH | 0.00202145 | ||||
Set Approval For... | 16599254 | 664 days ago | IN | 0 ETH | 0.00175665 | ||||
Mint | 16598407 | 664 days ago | IN | 0 ETH | 0.00326265 | ||||
Mint | 16598340 | 664 days ago | IN | 0 ETH | 0.00321585 | ||||
Mint | 16597956 | 664 days ago | IN | 0 ETH | 0.00322326 | ||||
Mint | 16597717 | 664 days ago | IN | 0 ETH | 0.00297723 | ||||
Mint | 16597711 | 664 days ago | IN | 0 ETH | 0.00383927 | ||||
Mint | 16597526 | 664 days ago | IN | 0 ETH | 0.00292112 | ||||
Mint | 16597522 | 664 days ago | IN | 0 ETH | 0.00402094 | ||||
Mint | 16597373 | 664 days ago | IN | 0 ETH | 0.00427491 | ||||
Mint | 16597369 | 664 days ago | IN | 0 ETH | 0.00314104 | ||||
Mint | 16597267 | 664 days ago | IN | 0 ETH | 0.0027749 | ||||
Mint | 16597261 | 664 days ago | IN | 0 ETH | 0.00285179 | ||||
Mint | 16597056 | 664 days ago | IN | 0 ETH | 0.00409406 | ||||
Mint | 16597001 | 664 days ago | IN | 0 ETH | 0.00281387 | ||||
Set Approval For... | 16596389 | 664 days ago | IN | 0 ETH | 0.00114555 | ||||
Mint | 16596283 | 664 days ago | IN | 0 ETH | 0.00288082 | ||||
Mint | 16596274 | 664 days ago | IN | 0 ETH | 0.00276813 | ||||
Mint | 16595962 | 664 days ago | IN | 0 ETH | 0.00249648 | ||||
Mint | 16595914 | 664 days ago | IN | 0 ETH | 0.00255692 | ||||
Mint | 16595903 | 664 days ago | IN | 0 ETH | 0.00294373 | ||||
Mint | 16595895 | 664 days ago | IN | 0 ETH | 0.00311179 | ||||
Mint | 16595804 | 664 days ago | IN | 0 ETH | 0.00359957 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
CheckTurtz
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT /* (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( @@@@@@@@@@@@@@(((((((((((((( (((((((((((((( @@@@@@@@@@@@@@(((((((((((((( (((((((((((((( @@@@@@@@@@@@@@(((((((((((((( (((((((((((((( @@@@@@@@@@@@@@(((((((((((((( (((((((((((((( @@@@@@@@@@@@@@(((((((((((((( (((((((((((((( @@@@@@@@@@@@@@(((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( */ // @title Check Turtz // @author @tom_hirst // @notice A fully on-chain, gamified Tiny Winged Turtlez x Checks derivative /* How it works: - Anyone can mint a Check Turtz NFT for free + gas - There is a mint limit of 1 Check Turtz NFT per wallet - Minting will last for 72 hours as an open edition with no max supply - Holding Tiny Winged Turtlez and/or Checks NFTs in the wallet you mint from unlocks differentiated art - Your minted Check Turtz NFT will receive a Colors trait based on the number of Tiny Winged Turtlez and/or Checks NFTs you hold - Example 1: If you hold 5 Tiny Winged Turtlez in your wallet when you mint, your Check Turtz NFT will have a Colors trait of 5 - Example 2: If you hold 10 Checks NFTs in your wallet when you mint, your Check Turtz NFT will have a Colors trait of 10 - Example 3: If you hold 5 Tiny Winged Turtlez and 10 Checks NFTs in your wallet when you mint, your Check Turtz NFT will have a Colors trait of 15 - The maximum Colors trait value is 80. This is the number of elements in the original Checks piece by @jackbutcher - Check Turtz NFTs with a Colors trait feature pseudo-random elements in their art - For example, if your Check Turtz NFT has a Colors trait value of 5, its artwork will have 5 pseudo-randomly coloured and positioned elements - Colours and positions used are distinct per Check Turtz NFT with differentiated art - The colour palette is inspired by the original Checks piece designed by @jackbutcher - Color traits are assigned at mint time and won't change thereafter - For example, your Check Turtz NFT will still have a Colors trait of 5, even if you no longer hold the 5 Tiny Winged Turtlez and/or Checks NFTs used to unlock it - Tiny Winged Turtlez and Checks NFTs are NOT burned - Check Turtz NFTs are burnable */ pragma solidity ^0.8.17; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/interfaces/IERC2981.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Base64.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "operator-filter-registry/src/DefaultOperatorFilterer.sol"; import "./lib/CheckTurtzDelegateBalance.sol"; import "./interfaces/IERC4906.sol"; contract CheckTurtz is ERC721, IERC2981, IERC4906, Ownable, DefaultOperatorFilterer, CheckTurtzDelegateBalance { address public immutable TINY_WINGED_TURTLEZ_ADDRESS; address public immutable CHECKS_ADDRESS; uint256 public mintEnds; // @dev Just in case address public checksV2Address; uint256 private _totalSupply; uint256 private nextTokenId; struct CheckTurt { uint16 colors; uint256 psuedoRandomNumber; bool darkMode; } mapping(uint256 => CheckTurt) public checkTurtz; mapping(address => bool) public hasMinted; string[80] private colorPalette = [ "#DB395E", "#602263", "#5C83CB", "#B1EFC9", "#25438C", "#7A2520", "#85C33C", "#C23532", "#2E668B", "#F6CBA6", "#DA3321", "#2D5352", "#5FCD8C", "#4291A8", "#EF8C37", "#535687", "#F2A43A", "#5ABAD3", "#D6F4E1", "#D1DF4F", "#A4C8EE", "#EF8933", "#A7DDF9", "#9DEFBF", "#525EAA", "#EC7368", "#FBEA5B", "#93CF98", "#EB5A2A", "#B82C36", "#EA3A2D", "#F6CB45", "#33758D", "#F09837", "#9AD9FB", "#F7DD9B", "#FAE663", "#F4BDBE", "#F7CA57", "#EE837D", "#ED7C30", "#3E8BA3", "#F0A0CA", "#4D3658", "#81D1EC", "#3B2F39", "#F2A93B", "#60B1F4", "#977A31", "#D5332F", "#E73E53", "#2F2243", "#DB4D58", "#F2A93C", "#5A9F3E", "#6D2F22", "#4068C1", "#F9DA4D", "#77D3DE", "#6A552A", "#8A2235", "#FAE272", "#EB4429", "#E0C963", "#F9DA4A", "#C7EDF2", "#F2B341", "#EA5B33", "#D97D2E", "#ABDD45", "#F2A840", "#EE828F", "#322F92", "#E8424E", "#2E4985", "#5FC9BF", "#F9DB49", "#4AA392", "#DE3237", "#7A5AB4" ]; uint8[80] private positions = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 ]; uint16[2][80] private coordinates = [ [600, 498], [708, 498], [816, 498], [924, 498], [1032, 498], [1140, 498], [1248, 498], [1356, 498], [600, 603], [708, 603], [816, 603], [924, 603], [1032, 603], [1140, 603], [1248, 603], [1356, 603], [600, 708], [708, 708], [816, 708], [924, 708], [1032, 708], [1140, 708], [1248, 708], [1356, 708], [600, 813], [708, 813], [816, 813], [924, 813], [1032, 813], [1140, 813], [1248, 813], [1356, 813], [600, 918], [708, 918], [816, 918], [924, 918], [1032, 918], [1140, 918], [1248, 918], [1356, 918], [600, 1023], [708, 1023], [816, 1023], [924, 1023], [1032, 1023], [1140, 1023], [1248, 1023], [1356, 1023], [600, 1128], [708, 1128], [816, 1128], [924, 1128], [1032, 1128], [1140, 1128], [1248, 1128], [1356, 1128], [600, 1233], [708, 1233], [816, 1233], [924, 1233], [1032, 1233], [1140, 1233], [1248, 1233], [1356, 1233], [600, 1338], [708, 1338], [816, 1338], [924, 1338], [1032, 1338], [1140, 1338], [1248, 1338], [1356, 1338], [600, 1443], [708, 1443], [816, 1443], [924, 1443], [1032, 1443], [1140, 1443], [1248, 1443], [1356, 1443] ]; error MintEndsInPast(); error EmptyTWTContract(); error EmptyChecksContract(); error ChecksV2AlreadySet(); error EmptyChecksV2Contract(); error MintingEnded(); error AlreadyMinted(); error TokenDoesNotExist(); error NotApprovedOrOwner(); constructor( uint256 _mintEnds, address _twtAddress, address _checksAddress, address _warmWalletAddress ) ERC721("Check Turtz", "CHECKTURTZ") CheckTurtzDelegateBalance(_warmWalletAddress) { if (block.timestamp > _mintEnds) { revert MintEndsInPast(); } if (_twtAddress == address(0)) { revert EmptyTWTContract(); } if (_checksAddress == address(0)) { revert EmptyChecksContract(); } mintEnds = _mintEnds; TINY_WINGED_TURTLEZ_ADDRESS = _twtAddress; CHECKS_ADDRESS = _checksAddress; } function totalSupply() external view returns (uint256) { return _totalSupply; } function addChecksV2Contract(address _checksV2Address) external onlyOwner { if (checksV2Address != address(0)) { revert ChecksV2AlreadySet(); } if (_checksV2Address == address(0)) { revert EmptyChecksV2Contract(); } checksV2Address = _checksV2Address; } function mint() external { if (block.timestamp > mintEnds) { revert MintingEnded(); } if (hasMinted[msg.sender]) { revert AlreadyMinted(); } uint256 tokenId = ++nextTokenId; // @dev Max supply 5,000 + 16,030 = 24,030 uint16 colors = 0; colors = uint16( delegateBalance(TINY_WINGED_TURTLEZ_ADDRESS) + delegateBalance(CHECKS_ADDRESS) ); if (checksV2Address != address(0)) { colors += uint16(delegateBalance(checksV2Address)); } if (colors > 0) { checkTurtz[tokenId].colors = colors < 81 ? colors : 80; checkTurtz[tokenId].psuedoRandomNumber = uint256( keccak256( abi.encodePacked(msg.sender, block.coinbase, _totalSupply) ) ); } hasMinted[msg.sender] = true; ++_totalSupply; _mint(msg.sender, tokenId); } function toggleTokenMode(uint256 tokenId) external { if (!_isApprovedOrOwner(msg.sender, tokenId)) { revert NotApprovedOrOwner(); } checkTurtz[tokenId].darkMode = !checkTurtz[tokenId].darkMode; emit MetadataUpdate(tokenId); } function getFrame(uint256 tokenId) internal view returns (string memory) { if (checkTurtz[tokenId].darkMode) { return "<path d='M2000 0H0V2000H2000V0Z' fill='#000000'/><path d='M1448.89 447.852H551.107V1552.15H1448.89V447.852Z' fill='#111111' />"; } return "<path d='M2000 0H0V2000H2000V0Z' fill='#efefef'/><path d='M1448.89 447.852H551.107V1552.15H1448.89V447.852Z' fill='#ffffff' />"; } function getDefaultTurt() internal pure returns (string memory) { return "<path d='M0.893005 0.897949H35.093L35.093 12.298H46.493V46.498H35.093L35.093 57.8979H0.893005V0.897949Z' fill='#65bc48' /><path d='M35.093 12.298H12.293V35.098H35.093V12.298Z' fill='#ffffff' /><path d='M35.1 23.698H23.7V35.098H35.1V23.698Z' fill='#000000' />"; } function getCheckTurt( uint256 tokenId, uint8 i ) internal view returns (string memory) { uint8 colorPaletteIndex = uint8( uint8(checkTurtz[tokenId].psuedoRandomNumber >> i) % colorPalette.length ); return string( abi.encodePacked( "<path d='M0.893005 0.897949H35.093L35.093 12.298H46.493V46.498H35.093L35.093 57.8979H0.893005V0.897949Z' fill='", colorPalette[colorPaletteIndex], "' /><path d='M35.093 12.298H12.293V35.098H35.093V12.298Z' fill='#ffffff' /><path d='M35.1 23.698H23.7V35.098H35.1V23.698Z' fill='#000000' />" ) ); } function shufflePositions( uint256 tokenId ) internal view returns (uint8[80] memory) { uint8[80] memory shuffledPositions = positions; for (uint i = 0; i < shuffledPositions.length; ) { uint j = checkTurtz[tokenId].psuedoRandomNumber % (i + 1); uint8 temp = shuffledPositions[i]; shuffledPositions[i] = shuffledPositions[j]; shuffledPositions[j] = temp; unchecked { ++i; } } return shuffledPositions; } function getTurtGrid( uint256 tokenId ) internal view returns (string memory grid) { for (uint8 i = 0; i < 80; ) { uint8[80] memory shuffledPositions = shufflePositions(tokenId); uint8 positionIndex = checkTurtz[tokenId].colors > 0 ? shuffledPositions[i] : i; if (i < checkTurtz[tokenId].colors) { grid = string( abi.encodePacked( grid, "<g transform='translate(", Strings.toString(coordinates[positionIndex][0]), " ", Strings.toString(coordinates[positionIndex][1]), ")'>", getCheckTurt(tokenId, i), "</g>" ) ); } else { grid = string( abi.encodePacked( grid, "<g transform='translate(", Strings.toString(coordinates[positionIndex][0]), " ", Strings.toString(coordinates[positionIndex][1]), ")'>", getDefaultTurt(), "</g>" ) ); } unchecked { ++i; } } return grid; } function getTokenIdSvg( uint256 tokenId ) internal view returns (string memory) { return string( abi.encodePacked( "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2000 2000'>", getFrame(tokenId), getTurtGrid(tokenId), "</svg>" ) ); } function getTokenIdMetadata( uint256 tokenId ) internal view returns (string memory metadata) { metadata = string( abi.encodePacked( '{"trait_type": "Mode", "value": "', checkTurtz[tokenId].darkMode ? "Dark" : "Light", '"}' ) ); if (checkTurtz[tokenId].colors > 0) { metadata = string( abi.encodePacked( metadata, ',{"trait_type": "Colors", "value": "', Strings.toString(checkTurtz[tokenId].colors), '"}' ) ); } return metadata; } function tokenURI( uint256 tokenId ) public view override returns (string memory) { if (!_exists(tokenId)) { revert TokenDoesNotExist(); } return string( abi.encodePacked( "data:application/json;base64,", Base64.encode( bytes( string( abi.encodePacked( '{"name": "Check Turtz #', Strings.toString(tokenId), '", "description": "Check Turtz is a fully on-chain, gamified Tiny Winged Turtlez x Checks derivative.", "image": "data:image/svg+xml;base64,', Base64.encode( bytes(getTokenIdSvg(tokenId)) ), '","attributes":[', getTokenIdMetadata(tokenId), "]}" ) ) ) ) ) ); } function burn(uint256 tokenId) external { if (!_isApprovedOrOwner(msg.sender, tokenId)) { revert NotApprovedOrOwner(); } --_totalSupply; _burn(tokenId); } function supportsInterface( bytes4 interfaceId ) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC2981).interfaceId || interfaceId == bytes4(0x49064906) || super.supportsInterface(interfaceId); } function setApprovalForAll( address operator, bool approved ) public override(IERC721, ERC721) onlyAllowedOperatorApproval(operator) { super.setApprovalForAll(operator, approved); } function approve( address operator, uint256 tokenId ) public override(IERC721, ERC721) onlyAllowedOperatorApproval(operator) { super.approve(operator, tokenId); } function transferFrom( address from, address to, uint256 tokenId ) public override(IERC721, ERC721) onlyAllowedOperator(from) { super.transferFrom(from, to, tokenId); } function safeTransferFrom( address from, address to, uint256 tokenId ) public override(IERC721, ERC721) onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId); } function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public override(IERC721, ERC721) onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId, data); } function royaltyInfo( uint256 tokenId, uint256 salePrice ) public view returns (address, uint256) { if (!_exists(tokenId)) { revert TokenDoesNotExist(); } return (owner(), (salePrice * 25) / 1000); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC721.sol) pragma solidity ^0.8.0; import "../token/ERC721/IERC721.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId, 1); // Check that tokenId was not minted by `_beforeTokenTransfer` hook require(!_exists(tokenId), "ERC721: token already minted"); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. // Given that tokens are minted one by one, it is impossible in practice that // this ever happens. Might change if we allow batch minting. // The ERC fails to describe this case. _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook owner = ERC721.ownerOf(tokenId); // Clear approvals delete _tokenApprovals[tokenId]; unchecked { // Cannot overflow, as that would require more tokens to be burned/transferred // out than the owner initially received through minting and transferring in. _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId, 1); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); // Clear approvals from the previous owner delete _tokenApprovals[tokenId]; unchecked { // `_balances[from]` cannot overflow for the same reason as described in `_burn`: // `from`'s balance is the number of token held, which is at least one before the current // transfer. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require // all 2**256 token ids to be minted, which in practice is impossible. _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. * - When `from` is zero, the tokens will be minted for `to`. * - When `to` is zero, ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256, /* firstTokenId */ uint256 batchSize ) internal virtual { if (batchSize > 1) { if (from != address(0)) { _balances[from] -= batchSize; } if (to != address(0)) { _balances[to] += batchSize; } } } /** * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. * - When `from` is zero, the tokens were minted for `to`. * - When `to` is zero, ``from``'s tokens were burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual {} }
// 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.8.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 have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol) pragma solidity ^0.8.0; /** * @dev Provides a set of functions to operate with Base64 strings. * * _Available since v4.5._ */ library Base64 { /** * @dev Base64 Encoding/Decoding Table */ string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * @dev Converts a `bytes` to its Bytes64 `string` representation. */ function encode(bytes memory data) internal pure returns (string memory) { /** * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol */ if (data.length == 0) return ""; // Loads the table into memory string memory table = _TABLE; // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter // and split into 4 numbers of 6 bits. // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up // - `data.length + 2` -> Round up // - `/ 3` -> Number of 3-bytes chunks // - `4 *` -> 4 characters for each chunk string memory result = new string(4 * ((data.length + 2) / 3)); /// @solidity memory-safe-assembly assembly { // Prepare the lookup table (skip the first "length" byte) let tablePtr := add(table, 1) // Prepare result pointer, jump over length let resultPtr := add(result, 32) // Run over the input, 3 bytes at a time for { let dataPtr := data let endPtr := add(data, mload(data)) } lt(dataPtr, endPtr) { } { // Advance 3 bytes dataPtr := add(dataPtr, 3) let input := mload(dataPtr) // To write each character, shift the 3 bytes (18 bits) chunk // 4 times in blocks of 6 bits for each character (18, 12, 6, 0) // and apply logical AND with 0x3F which is the number of // the previous character in the ASCII table prior to the Base64 Table // The result is then added to the table to get the character to write, // and finally write it in the result pointer but with a left shift // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F)))) resultPtr := add(resultPtr, 1) // Advance } // When data `bytes` is not exactly 3 bytes long // it is padded with `=` characters at the end switch mod(mload(data), 3) case 1 { mstore8(sub(resultPtr, 1), 0x3d) mstore8(sub(resultPtr, 2), 0x3d) } case 2 { mstore8(sub(resultPtr, 1), 0x3d) } } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import "@openzeppelin/contracts/interfaces/IERC165.sol"; import "@openzeppelin/contracts/interfaces/IERC721.sol"; /// @title EIP-721 Metadata Update Extension interface IERC4906 is IERC165, IERC721 { /// @dev This event emits when the metadata of a token is changed. /// So that the third-party platforms such as NFT market could /// timely update the images and related attributes of the NFT. event MetadataUpdate(uint256 _tokenId); /// @dev This event emits when the metadata of a range of tokens is changed. /// So that the third-party platforms such as NFT market could /// timely update the images and related attributes of the NFTs. event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId); }
// SPDX-License-Identifier: MIT /* (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( (((((((((((((( @@@@@@@@@@@@@@(((((((((((((( (((((((((((((( @@@@@@@@@@@@@@(((((((((((((( (((((((((((((( @@@@@@@@@@@@@@(((((((((((((( (((((((((((((( @@@@@@@@@@@@@@(((((((((((((( (((((((((((((( @@@@@@@@@@@@@@(((((((((((((( (((((((((((((( @@@@@@@@@@@@@@(((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((( */ // @title Check Turtz Delegate Balance // @author @tom_hirst // @notice Checks the token balance of a delegate wallet // @dev Uses Warm Wallet (warm.xyz) pragma solidity ^0.8.17; interface IWarmWallet { function balanceOf( address contractAddress, address owner ) external view returns (uint256); } error EmptyWarmWalletContract(); contract CheckTurtzDelegateBalance { address public immutable WARM_WALLET_ADDRESS; constructor(address _warmWalletAddress) { if (_warmWalletAddress == address(0)) { revert EmptyWarmWalletContract(); } WARM_WALLET_ADDRESS = _warmWalletAddress; } function delegateBalance( address contractAddress ) internal view returns (uint256) { return IWarmWallet(WARM_WALLET_ADDRESS).balanceOf( contractAddress, msg.sender ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {OperatorFilterer} from "./OperatorFilterer.sol"; import {CANONICAL_CORI_SUBSCRIPTION} from "./lib/Constants.sol"; /** * @title DefaultOperatorFilterer * @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription. * @dev Please note that if your token contract does not provide an owner with EIP-173, it must provide * administration methods on the contract itself to interact with the registry otherwise the subscription * will be locked to the options set during construction. */ abstract contract DefaultOperatorFilterer is OperatorFilterer { /// @dev The constructor that is called when the contract is being deployed. constructor() OperatorFilterer(CANONICAL_CORI_SUBSCRIPTION, true) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; interface IOperatorFilterRegistry { /** * @notice Returns true if operator is not filtered for a given token, either by address or codeHash. Also returns * true if supplied registrant address is not registered. */ function isOperatorAllowed(address registrant, address operator) external view returns (bool); /** * @notice Registers an address with the registry. May be called by address itself or by EIP-173 owner. */ function register(address registrant) external; /** * @notice Registers an address with the registry and "subscribes" to another address's filtered operators and codeHashes. */ function registerAndSubscribe(address registrant, address subscription) external; /** * @notice Registers an address with the registry and copies the filtered operators and codeHashes from another * address without subscribing. */ function registerAndCopyEntries(address registrant, address registrantToCopy) external; /** * @notice Unregisters an address with the registry and removes its subscription. May be called by address itself or by EIP-173 owner. * Note that this does not remove any filtered addresses or codeHashes. * Also note that any subscriptions to this registrant will still be active and follow the existing filtered addresses and codehashes. */ function unregister(address addr) external; /** * @notice Update an operator address for a registered address - when filtered is true, the operator is filtered. */ function updateOperator(address registrant, address operator, bool filtered) external; /** * @notice Update multiple operators for a registered address - when filtered is true, the operators will be filtered. Reverts on duplicates. */ function updateOperators(address registrant, address[] calldata operators, bool filtered) external; /** * @notice Update a codeHash for a registered address - when filtered is true, the codeHash is filtered. */ function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external; /** * @notice Update multiple codeHashes for a registered address - when filtered is true, the codeHashes will be filtered. Reverts on duplicates. */ function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external; /** * @notice Subscribe an address to another registrant's filtered operators and codeHashes. Will remove previous * subscription if present. * Note that accounts with subscriptions may go on to subscribe to other accounts - in this case, * subscriptions will not be forwarded. Instead the former subscription's existing entries will still be * used. */ function subscribe(address registrant, address registrantToSubscribe) external; /** * @notice Unsubscribe an address from its current subscribed registrant, and optionally copy its filtered operators and codeHashes. */ function unsubscribe(address registrant, bool copyExistingEntries) external; /** * @notice Get the subscription address of a given registrant, if any. */ function subscriptionOf(address addr) external returns (address registrant); /** * @notice Get the set of addresses subscribed to a given registrant. * Note that order is not guaranteed as updates are made. */ function subscribers(address registrant) external returns (address[] memory); /** * @notice Get the subscriber at a given index in the set of addresses subscribed to a given registrant. * Note that order is not guaranteed as updates are made. */ function subscriberAt(address registrant, uint256 index) external returns (address); /** * @notice Copy filtered operators and codeHashes from a different registrantToCopy to addr. */ function copyEntriesOf(address registrant, address registrantToCopy) external; /** * @notice Returns true if operator is filtered by a given address or its subscription. */ function isOperatorFiltered(address registrant, address operator) external returns (bool); /** * @notice Returns true if the hash of an address's code is filtered by a given address or its subscription. */ function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool); /** * @notice Returns true if a codeHash is filtered by a given address or its subscription. */ function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool); /** * @notice Returns a list of filtered operators for a given address or its subscription. */ function filteredOperators(address addr) external returns (address[] memory); /** * @notice Returns the set of filtered codeHashes for a given address or its subscription. * Note that order is not guaranteed as updates are made. */ function filteredCodeHashes(address addr) external returns (bytes32[] memory); /** * @notice Returns the filtered operator at the given index of the set of filtered operators for a given address or * its subscription. * Note that order is not guaranteed as updates are made. */ function filteredOperatorAt(address registrant, uint256 index) external returns (address); /** * @notice Returns the filtered codeHash at the given index of the list of filtered codeHashes for a given address or * its subscription. * Note that order is not guaranteed as updates are made. */ function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32); /** * @notice Returns true if an address has registered */ function isRegistered(address addr) external returns (bool); /** * @dev Convenience method to compute the code hash of an arbitrary contract */ function codeHashOf(address addr) external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; address constant CANONICAL_OPERATOR_FILTER_REGISTRY_ADDRESS = 0x000000000000AAeB6D7670E522A718067333cd4E; address constant CANONICAL_CORI_SUBSCRIPTION = 0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6;
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol"; import {CANONICAL_OPERATOR_FILTER_REGISTRY_ADDRESS} from "./lib/Constants.sol"; /** * @title OperatorFilterer * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another * registrant's entries in the OperatorFilterRegistry. * @dev This smart contract is meant to be inherited by token contracts so they can use the following: * - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods. * - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods. * Please note that if your token contract does not provide an owner with EIP-173, it must provide * administration methods on the contract itself to interact with the registry otherwise the subscription * will be locked to the options set during construction. */ abstract contract OperatorFilterer { /// @dev Emitted when an operator is not allowed. error OperatorNotAllowed(address operator); IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY = IOperatorFilterRegistry(CANONICAL_OPERATOR_FILTER_REGISTRY_ADDRESS); /// @dev The constructor that is called when the contract is being deployed. constructor(address subscriptionOrRegistrantToCopy, bool subscribe) { // If an inheriting token contract is deployed to a network without the registry deployed, the modifier // will not revert, but the contract will need to be registered with the registry once it is deployed in // order for the modifier to filter addresses. if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) { if (subscribe) { OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy); } else { if (subscriptionOrRegistrantToCopy != address(0)) { OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy); } else { OPERATOR_FILTER_REGISTRY.register(address(this)); } } } } /** * @dev A helper function to check if an operator is allowed. */ modifier onlyAllowedOperator(address from) virtual { // Allow spending tokens from addresses with balance // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred // from an EOA. if (from != msg.sender) { _checkFilterOperator(msg.sender); } _; } /** * @dev A helper function to check if an operator approval is allowed. */ modifier onlyAllowedOperatorApproval(address operator) virtual { _checkFilterOperator(operator); _; } /** * @dev A helper function to check if an operator is allowed. */ function _checkFilterOperator(address operator) internal view virtual { // Check registry code length to facilitate testing in environments without a deployed registry. if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) { // under normal circumstances, this function will revert rather than return false, but inheriting contracts // may specify their own OperatorFilterRegistry implementations, which may behave differently if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) { revert OperatorNotAllowed(operator); } } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"_mintEnds","type":"uint256"},{"internalType":"address","name":"_twtAddress","type":"address"},{"internalType":"address","name":"_checksAddress","type":"address"},{"internalType":"address","name":"_warmWalletAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyMinted","type":"error"},{"inputs":[],"name":"ChecksV2AlreadySet","type":"error"},{"inputs":[],"name":"EmptyChecksContract","type":"error"},{"inputs":[],"name":"EmptyChecksV2Contract","type":"error"},{"inputs":[],"name":"EmptyTWTContract","type":"error"},{"inputs":[],"name":"EmptyWarmWalletContract","type":"error"},{"inputs":[],"name":"MintEndsInPast","type":"error"},{"inputs":[],"name":"MintingEnded","type":"error"},{"inputs":[],"name":"NotApprovedOrOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[],"name":"TokenDoesNotExist","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":false,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","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":[],"name":"CHECKS_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TINY_WINGED_TURTLEZ_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WARM_WALLET_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_checksV2Address","type":"address"}],"name":"addChecksV2Contract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","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":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"checkTurtz","outputs":[{"internalType":"uint16","name":"colors","type":"uint16"},{"internalType":"uint256","name":"psuedoRandomNumber","type":"uint256"},{"internalType":"bool","name":"darkMode","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checksV2Address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hasMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintEnds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"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":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"toggleTokenMode","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"}]
Contract Creation Code
60e0346200206857600062004b613881900390601f8201601f191684016001600160401b03811185821017620020515791808592608094604052833981010312620020655781516200005460208401620020bc565b916200007160606200006960408701620020bc565b9501620020bc565b906040516200008081620020a0565b600b81526a21b432b1b5902a3ab93a3d60a91b602082015260405190620000a782620020a0565b600a82526921a422a1a5aa2aa92a2d60b11b60208301528051906001600160401b03821162002051578190620000de8554620020d1565b601f81116200201d575b50602090601f831160011462001fb457859262001fa8575b50508160011b916000199060031b1c19161782555b8051906001600160401b03821162001f9457819062000136600154620020d1565b601f811162001f47575b50602090601f831160011462001ed057849262001ec4575b50508160011b916000199060031b1c1916176001555b60068054336001600160a01b0319821681179092556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a36daaeb6d7670e522a718067333cd4e803b62001e3b575b50906001600160a01b0381161562001e2957608052604051620001ea816200206d565b604051620001f881620020a0565b60078152662344423339354560c81b602082015281526040516200021c81620020a0565b60078152662336303232363360c81b602082015260208201526040516200024381620020a0565b6007815266119aa19c19a1a160c91b602082015260408201526040516200026a81620020a0565b60078152662342314546433960c81b602082015260608201526040516200029181620020a0565b60078152662332353433384360c81b60208201526080820152604051620002b881620020a0565b60078152660233741323532360cc1b602082015260a0820152604051620002df81620020a0565b60078152662338354333334360c81b602082015260c08201526040516200030681620020a0565b600781526611a199199a999960c91b602082015260e08201526040516200032d81620020a0565b60078152661199229b1b1c2160c91b60208201526101008201526040516200035581620020a0565b600781526611a31b21a1209b60c91b60208201526101208201526040516200037d81620020a0565b60078152662344413333323160c81b6020820152610140820152604051620003a581620020a0565b60078152661199221a999a9960c91b6020820152610160820152604051620003cd81620020a0565b60078152662335464344384360c81b6020820152610180820152604051620003f581620020a0565b60078152660466864726282760cb1b60208201526101a08201526040516200041d81620020a0565b60078152662345463843333760c81b60208201526101c08201526040516200044581620020a0565b60078152662335333536383760c81b60208201526101e08201526040516200046d81620020a0565b60078152662346324134334160c81b60208201526102008201526040516200049581620020a0565b60078152662335414241443360c81b6020820152610220820152604051620004bd81620020a0565b60078152662344364634453160c81b6020820152610240820152604051620004e581620020a0565b600781526611a218a2231a2360c91b60208201526102608201526040516200050d81620020a0565b60078152662341344338454560c81b60208201526102808201526040516200053581620020a0565b60078152662345463839333360c81b60208201526102a08201526040516200055d81620020a0565b60078152662341374444463960c81b60208201526102c08201526040516200058581620020a0565b6007815266119ca222a3212360c91b60208201526102e0820152604051620005ad81620020a0565b60078152662335323545414160c81b6020820152610300820152604051620005d581620020a0565b60078152660468a866e666c760cb1b6020820152610320820152604051620005fd81620020a0565b600781526611a32122a09aa160c91b60208201526103408201526040516200062581620020a0565b60078152660467266868c72760cb1b60208201526103608201526040516200064d81620020a0565b60078152662345423541324160c81b60208201526103808201526040516200067581620020a0565b600781526611a11c1921999b60c91b60208201526103a08201526040516200069d81620020a0565b600781526608d1504cd04c9160ca1b60208201526103c0820152604051620006c581620020a0565b60078152662346364342343560c81b60208201526103e0820152604051620006ed81620020a0565b600781526608cccccdcd4e1160ca1b60208201526104008201526040516200071581620020a0565b60078152662346303938333760c81b60208201526104208201526040516200073d81620020a0565b6007815266119ca0a21ca32160c91b60208201526104408201526040516200076581620020a0565b600781526611a31ba2221ca160c91b60208201526104608201526040516200078d81620020a0565b60078152662346414536363360c81b6020820152610480820152604051620007b581620020a0565b60078152662346344244424560c81b60208201526104a0820152604051620007dd81620020a0565b60078152662346374341353760c81b60208201526104c08201526040516200080581620020a0565b600781526608d1514e0ccdd160ca1b60208201526104e08201526040516200082d81620020a0565b60078152660234544374333360cc1b60208201526105008201526040516200085581620020a0565b60078152662333453842413360c81b60208201526105208201526040516200087d81620020a0565b60078152662346304130434160c81b6020820152610540820152604051620008a581620020a0565b60078152660466888666c6a760cb1b6020820152610560820152604051620008cd81620020a0565b60078152662338314431454360c81b6020820152610580820152604051620008f581620020a0565b60078152662333423246333960c81b60208201526105a08201526040516200091d81620020a0565b600781526611a319209c99a160c91b60208201526105c08201526040516200094581620020a0565b600781526608cd8c108c518d60ca1b60208201526105e08201526040516200096d81620020a0565b60078152662339373741333160c81b60208201526106008201526040516200099581620020a0565b600781526611a21a9999992360c91b6020820152610620820152604051620009bd81620020a0565b60078152662345373345353360c81b6020820152610640820152604051620009e581620020a0565b60078152662332463232343360c81b602082015261066082015260405162000a0d81620020a0565b6007815266046888468886a760cb1b602082015261068082015260405162000a3581620020a0565b60078152662346324139334360c81b60208201526106a082015260405162000a5d81620020a0565b60078152662335413946334560c81b60208201526106c082015260405162000a8581620020a0565b6007815266119b221923191960c91b60208201526106e082015260405162000aad81620020a0565b60078152662334303638433160c81b602082015261070082015260405162000ad581620020a0565b600781526608d18e51104d1160ca1b602082015261072082015260405162000afd81620020a0565b60078152662337374433444560c81b602082015261074082015260405162000b2581620020a0565b60078152662336413535324160c81b602082015261076082015260405162000b4d81620020a0565b60078152662338413232333560c81b602082015261078082015260405162000b7581620020a0565b600781526611a320a2991b9960c91b60208201526107a082015260405162000b9d81620020a0565b60078152662345423434323960c81b60208201526107c082015260405162000bc581620020a0565b60078152662345304339363360c81b60208201526107e082015260405162000bed81620020a0565b60078152662346394441344160c81b602082015261080082015260405162000c1581620020a0565b600781526611a19ba2a2231960c91b602082015261082082015260405162000c3d81620020a0565b60078152662346324233343160c81b602082015261084082015260405162000c6581620020a0565b60078152662345413542333360c81b602082015261086082015260405162000c8d81620020a0565b60078152662344393744324560c81b602082015261088082015260405162000cb581620020a0565b60078152662341424444343560c81b60208201526108a082015260405162000cdd81620020a0565b60078152660234632413834360cc1b60208201526108c082015260405162000d0581620020a0565b600781526611a2a29c191c2360c91b60208201526108e082015260405162000d2d81620020a0565b600781526611999919231c9960c91b602082015261090082015260405162000d5581620020a0565b60078152662345383432344560c81b602082015261092082015260405162000d7d81620020a0565b60078152662332453439383560c81b602082015261094082015260405162000da581620020a0565b6007815266119aa3219ca12360c91b602082015261096082015260405162000dcd81620020a0565b60078152662346394442343960c81b602082015261098082015260405162000df581620020a0565b6007815266119a20a0999c9960c91b60208201526109a082015260405162000e1d81620020a0565b60078152662344453332333760c81b60208201526109c082015260405162000e4581620020a0565b600781526608cdd04d50508d60ca1b60208201526109e0820152600d9082905b6050821062001ce95750505060405162000e7f816200206d565b81815260016020820152600260408201526003606082015260046080820152600560a0820152600660c0820152600760e082015260086101008201526009610120820152600a610140820152600b610160820152600c610180820152600d6101a0820152600e6101c0820152600f6101e08201526010610200820152601161022082015260126102408201526013610260820152601461028082015260156102a082015260166102c082015260176102e082015260186103008201526019610320820152601a610340820152601b610360820152601c610380820152601d6103a0820152601e6103c0820152601f6103e08201526020610400820152602161042082015260226104408201526023610460820152602461048082015260256104a082015260266104c082015260276104e082015260286105008201526029610520820152602a610540820152602b610560820152602c610580820152602d6105a0820152602e6105c0820152602f6105e08201526030610600820152603161062082015260326106408201526033610660820152603461068082015260356106a082015260366106c082015260376106e082015260386107008201526039610720820152603a610740820152603b610760820152603c610780820152603d6107a0820152603e6107c0820152603f6107e08201526040610800820152604161082082015260426108408201526043610860820152604461088082015260456108a082015260466108c082015260476108e082015260486109008201526049610920820152604a610940820152604b610960820152604c610980820152604d6109a0820152604e6109c0820152604f6109e0820152815b6002811062001c9e57508190825b6010811062001c6e575050605f556040516200111f816200206d565b6040516200112d81620020a0565b61025881526101f2602082015281526040516200114a81620020a0565b6102c481526101f2602082015260208201526040516200116a81620020a0565b61033081526101f2602082015260408201526040516200118a81620020a0565b61039c81526101f260208201526060820152604051620011aa81620020a0565b61040881526101f260208201526080820152604051620011ca81620020a0565b61047481526101f2602082015260a0820152604051620011ea81620020a0565b6104e081526101f2602082015260c08201526040516200120a81620020a0565b61054c81526101f2602082015260e08201526040516200122a81620020a0565b610258815261025b60208201526101008201526040516200124b81620020a0565b6102c4815261025b60208201526101208201526040516200126c81620020a0565b610330815261025b60208201526101408201526040516200128d81620020a0565b61039c815261025b6020820152610160820152604051620012ae81620020a0565b610408815261025b6020820152610180820152604051620012cf81620020a0565b610474815261025b60208201526101a0820152604051620012f081620020a0565b6104e0815261025b60208201526101c08201526040516200131181620020a0565b61054c815261025b60208201526101e08201526040516200133281620020a0565b61025881526102c460208201526102008201526040516200135381620020a0565b6102c481526102c460208201526102208201526040516200137481620020a0565b61033081526102c460208201526102408201526040516200139581620020a0565b61039c81526102c46020820152610260820152604051620013b681620020a0565b61040881526102c46020820152610280820152604051620013d781620020a0565b61047481526102c460208201526102a0820152604051620013f881620020a0565b6104e081526102c460208201526102c08201526040516200141981620020a0565b61054c81526102c460208201526102e08201526040516200143a81620020a0565b610258815261032d60208201526103008201526040516200145b81620020a0565b6102c4815261032d60208201526103208201526040516200147c81620020a0565b610330815261032d60208201526103408201526040516200149d81620020a0565b61039c815261032d6020820152610360820152604051620014be81620020a0565b610408815261032d6020820152610380820152604051620014df81620020a0565b610474815261032d60208201526103a08201526040516200150081620020a0565b6104e0815261032d60208201526103c08201526040516200152181620020a0565b61054c815261032d60208201526103e08201526040516200154281620020a0565b610258815261039660208201526104008201526040516200156381620020a0565b6102c4815261039660208201526104208201526040516200158481620020a0565b61033081526103966020820152610440820152604051620015a581620020a0565b61039c81526103966020820152610460820152604051620015c681620020a0565b61040881526103966020820152610480820152604051620015e781620020a0565b610474815261039660208201526104a08201526040516200160881620020a0565b6104e0815261039660208201526104c08201526040516200162981620020a0565b61054c815261039660208201526104e08201526040516200164a81620020a0565b61025881526103ff60208201526105008201526040516200166b81620020a0565b6102c481526103ff60208201526105208201526040516200168c81620020a0565b61033081526103ff6020820152610540820152604051620016ad81620020a0565b61039c81526103ff6020820152610560820152604051620016ce81620020a0565b61040881526103ff6020820152610580820152604051620016ef81620020a0565b61047481526103ff60208201526105a08201526040516200171081620020a0565b6104e081526103ff60208201526105c08201526040516200173181620020a0565b61054c81526103ff60208201526105e08201526040516200175281620020a0565b610258815261046860208201526106008201526040516200177381620020a0565b6102c4815261046860208201526106208201526040516200179481620020a0565b61033081526104686020820152610640820152604051620017b581620020a0565b61039c81526104686020820152610660820152604051620017d681620020a0565b61040881526104686020820152610680820152604051620017f781620020a0565b610474815261046860208201526106a08201526040516200181881620020a0565b6104e0815261046860208201526106c08201526040516200183981620020a0565b61054c815261046860208201526106e08201526040516200185a81620020a0565b61025881526104d160208201526107008201526040516200187b81620020a0565b6102c481526104d160208201526107208201526040516200189c81620020a0565b61033081526104d16020820152610740820152604051620018bd81620020a0565b61039c81526104d16020820152610760820152604051620018de81620020a0565b61040881526104d16020820152610780820152604051620018ff81620020a0565b61047481526104d160208201526107a08201526040516200192081620020a0565b6104e081526104d160208201526107c08201526040516200194181620020a0565b61054c81526104d160208201526107e08201526040516200196281620020a0565b610258815261053a60208201526108008201526040516200198381620020a0565b6102c4815261053a6020820152610820820152604051620019a481620020a0565b610330815261053a6020820152610840820152604051620019c581620020a0565b61039c815261053a6020820152610860820152604051620019e681620020a0565b610408815261053a602082015261088082015260405162001a0781620020a0565b610474815261053a60208201526108a082015260405162001a2881620020a0565b6104e0815261053a60208201526108c082015260405162001a4981620020a0565b61054c815261053a60208201526108e082015260405162001a6a81620020a0565b61025881526105a3602082015261090082015260405162001a8b81620020a0565b6102c481526105a3602082015261092082015260405162001aac81620020a0565b61033081526105a3602082015261094082015260405162001acd81620020a0565b61039c81526105a3602082015261096082015260405162001aee81620020a0565b61040881526105a3602082015261098082015260405162001b0f81620020a0565b61047481526105a360208201526109a082015260405162001b3081620020a0565b6104e081526105a360208201526109c082015260405162001b5181620020a0565b61054c81526105a360208201526109e0820152606082915b6050831062001c1d575050505080421162001c0b576001600160a01b0382161562001bf9576001600160a01b0383161562001be75760075560a05260c052604051612a19908162002128823960805181818161118a01526128aa015260a0518181816117c90152611a33015260c0518181816117f20152611bfb0152f35b60405163c6eb2ce760e01b8152600490fd5b60405163205cb9a960e21b8152600490fd5b604051633d24da4f60e01b8152600490fd5b80518490855b6002811062001c445750506020600192839285550192019201919062001b69565b9091602060019161ffff9081865116918560041b90811b9283911b16911916179301910162001c23565b9091602062001c946001928460ff875116919060031b60ff811b9283911b169119161790565b9301910162001103565b82835b6020811062001cb95750605d820155600101620010f5565b9290602062001cdf6001928660ff865116919060031b60ff811b9283911b169119161790565b9201930162001ca1565b80518051906001600160401b03821162001e155762001d098554620020d1565b601f811162001dd5575b50602090601f831160011462001d635792826001949360209386958a9262001d57575b5050600019600383901b1c191690841b1786555b0193019101909162000e65565b01519050388062001d36565b908587526020872091875b601f198516811062001dbc575083602093600196938796938794601f1981161062001da2575b505050811b01865562001d4a565b015160001960f88460031b161c1916905538808062001d94565b9192602060018192868501518155019401920162001d6e565b62001e0390868852602088206005601f8601811c8201926020871062001e0a575b601f01901c01906200210e565b3862001d13565b919250829162001df6565b634e487b7160e01b86526041600452602486fd5b6040516350971b6960e01b8152600490fd5b803b1562001ec057818091604460405180948193633e9f1edf60e11b8352306004840152733cc6cdda760b79bafa08df41ecfa224f810dceb660248401525af1801562001eb55715620001c7576001600160401b03811162001ea15760405238620001c7565b634e487b7160e01b82526041600452602482fd5b6040513d84823e3d90fd5b5080fd5b01519050388062000158565b6001855260008051602062004b418339815191529250601f198416855b81811062001f2e575090846001959493921062001f14575b505050811b016001556200016e565b015160001960f88460031b161c1916905538808062001f05565b9293602060018192878601518155019501930162001eed565b6001855262001f829060008051602062004b41833981519152601f850160051c8101916020861062001f89575b601f0160051c01906200210e565b3862000140565b909150819062001f74565b634e487b7160e01b83526041600452602483fd5b01519050388062000100565b858052602086209250601f198416865b81811062002004575090846001959493921062001fea575b505050811b01825562000115565b015160001960f88460031b161c1916905538808062001fdc565b9293602060018192878601518155019501930162001fc4565b6200204a9086805260208720601f850160051c8101916020861062001f8957601f0160051c01906200210e565b38620000e8565b634e487b7160e01b84526041600452602484fd5b80fd5b600080fd5b610a0081019081106001600160401b038211176200208a57604052565b634e487b7160e01b600052604160045260246000fd5b604081019081106001600160401b038211176200208a57604052565b51906001600160a01b03821682036200206857565b90600182811c9216801562002103575b6020831014620020ed57565b634e487b7160e01b600052602260045260246000fd5b91607f1691620020e1565b8181106200211a575050565b600081556001016200210e56fe608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a714611ceb5750806306fdde0314611c48578063081812fc14611c2a5780630869806e14611be5578063095ea7b314611a6257806310fef2da14611a1d5780631249c58b1461178357806318160ddd1461176557806323b872dd146117205780632a55205a146116ba57806338e21cce1461167b5780633d317ed01461160757806340de28291461159657806341f434341461156d57806342842e0e1461151557806342966c68146114465780636352211e14611416578063685eca95146113ed57806370a0823114611356578063715018a6146112f95780638d899ea4146112ad5780638da5cb5b1461128457806395d89b41146111b9578063a085048714611174578063a22cb46514611090578063b88d4fde14610fa7578063c87b56dd146102a6578063e985e9c514610250578063f2fde38b1461018c5763fcfae6081461016957600080fd5b34610187576000366003190112610187576020600754604051908152f35b600080fd5b34610187576020366003190112610187576101a5611dd0565b6101ad611ee0565b6001600160a01b039081169081156101fc57600654826001600160601b0360a01b821617600655167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b3461018757604036600319011261018757610269611dd0565b610271611de6565b9060018060a01b03809116600052600560205260406000209116600052602052602060ff604060002054166040519015158152f35b34610187576020366003190112610187576004356000908152600260205260409020546001600160a01b031615610f95576102e2600435612274565b6102ed6004356123b7565b60009160605b605060ff85161015610ba557610a0060405161030e81611e4d565b36903760405180605d60005b6050601f820110610a19575060ff6101e091548181168452818160081c166020850152818160101c166040850152818160181c166060850152818160201c166080850152818160281c1660a0850152818160301c1660c0850152818160381c1660e0850152818160401c16610100850152818160481c16610120850152818160501c16610140850152818160581c16610160850152818160601c16610180850152818160681c166101a0850152818160701c166101c085015260781c169101526103e381611e4d565b60005b6050811061098c57506004356000908152600b602052604090205461ffff16156109855761041960ff9182871690612525565b51165b600435600052600b60205261ffff6040600020541660ff86161060001461073f57605081101561072957606001549061046661ffff61045c818516612274565b9360101c16612274565b600435600052600b60205260ff605081600160406000200154818a161c160616605081101561072957600d0190604051917f3c7061746820643d274d302e38393330303520302e3839373934394833352e3060208401527f39334c33352e3039332031322e3239384834362e3439335634362e343938483360408401527f352e3039334c33352e3039332035372e3839373948302e38393330303556302e60608401526e3839373934395a272066696c6c3d2760881b608084015260009080549061053082611faa565b916001811690811561070457506001146106c9575b505060019383631e17b39f60e11b6106bf9461061a608c60ff9a98877f27202f3e3c7061746820643d274d33352e3039332031322e3239384831322e32604099527f39335633352e3039384833352e3039335631322e3239385a272066696c6c3d2760208201527f2366666666666627202f3e3c7061746820643d274d33352e312032332e363938898201527f4832332e375633352e3039384833352e315632332e3639385a272066696c6c3d60608201526b13919818181818181390179f60a11b608082015203606c810186520184611ea2565b6214939f60e91b855197856106398a975180926020808b019101611d88565b860177078ce40e8e4c2dce6ccdee4da7a4ee8e4c2dce6d8c2e8ca560431b6020820152610670825180936020603885019101611d88565b01600160fd1b60388201528251906106918260399560208785019101611d88565b01918201528251906106ac82603c9560208785019101611d88565b0191820152036020810184520182611ea2565b945b0116926102f3565b90915060005260206000206000905b8282106106ed5750508201608f018383610545565b60018160209254608f8589010152019101906106d8565b60ff1916608f8088019190915283151590930286019092019250859150849050610545565b634e487b7160e01b600052603260045260246000fd5b605081101561072957606001549061075e61ffff61045c818516612274565b916040518061014081011067ffffffffffffffff6101408301111761096f57604060019382631e17b39f60e11b60ff9761014061096996018552610102835260208301927f3c7061746820643d274d302e38393330303520302e3839373934394833352e3084527f39334c33352e3039332031322e3239384834362e3439335634362e3439384833868201527f352e3039334c33352e3039332035372e3839373948302e38393330303556302e60608201527f3839373934395a272066696c6c3d272336356263343827202f3e3c706174682060808201527f643d274d33352e3039332031322e3239384831322e3239335633352e3039384860a08201527f33352e3039335631322e3239385a272066696c6c3d272366666666666627202f60c08201527f3e3c7061746820643d274d33352e312032332e3639384832332e375633352e3060e08201527f39384833352e315632332e3639385a272066696c6c3d2723303030303030272061010082015261179f60f11b6101208201526214939f60e91b865198866108fa8b985180926020808c019101611d88565b870177078ce40e8e4c2dce6ccdee4da7a4ee8e4c2dce6d8c2e8ca560431b6020820152610931825180936020603885019101611d88565b01600160fd1b60388201528351906109528260399660208885019101611d88565b019283015251906106ac82603c9586840190611d88565b946106c1565b634e487b7160e01b600052604160045260246000fd5b508361041c565b600435600052600b602052600190816040600020015491810191828211610a035782156109ed57826109e7910660ff6109c58487612525565b5116926109e060ff6109d78489612525565b51169187612525565b5284612525565b526103e6565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b90916001610400602092855460ff8116825260ff8160081c168583015260ff8160101c16604083015260ff8160181c16606083015260ff8160808282891c1681860152828260a0828260281c1681890152828260c095828260301c16878c0152828260381c1660e08c0152828260401c166101008c0152828260481c166101208c0152828260501c166101408c0152828260581c166101608c0152828260601c166101808c0152828260681c166101a08c0152828260701c166101c08c0152828260781c166101e08c01521c16610200890152828260881c16610220890152828260901c16610240890152828260981c166102608901521c16610280860152828260a81c166102a0860152828260b01c166102c0860152828260b81c166102e08601521c1661030083015260ff8160c81c1661032083015260ff8160d01c1661034083015260ff8160d81c1661036083015260ff8160e01c1661038083015260ff8160e81c166103a083015260ff8160f01c166103c083015260f81c6103e0820152019301910161031a565b90610c5560d5610c5a610e6f94610c556066610ed6986040519384917f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323060208401527f30302f737667272076696577426f783d2730203020323030302032303030273e6040840152610c21815180926020606087019101611d88565b8201610c37825180936020606085019101611d88565b01651e17b9bb339f60d11b6060820152036046810184520182611ea2565b61211d565b92600435600052600b60205260ff60026040600020015416600014610f7257604051610c8581611e6a565b60048152634461726b60e01b60208201525b60405160208101917f7b2274726169745f74797065223a20224d6f6465222c202276616c7565223a208352601160f91b6040830152610ce0815180926020604186019101611d88565b8101610d0360438361227d60f01b93846041820152036023810185520183611ea2565b8192600435600052600b60205261ffff8060406000205416610eda575b505050506040519485927f7b226e616d65223a2022436865636b20547572747a20230000000000000000006020850152610d64815180926020603788019101611d88565b83017f222c20226465736372697074696f6e223a2022436865636b20547572747a206960378201527f7320612066756c6c79206f6e2d636861696e2c2067616d69666965642054696e60578201527f792057696e67656420547572746c657a207820436865636b732064657269766160778201527f746976652e222c2022696d616765223a2022646174613a696d6167652f73766760978201526b0ade1b5b0ed8985cd94d8d0b60a21b60b7820152610e2782518093602060c385019101611d88565b016f222c2261747472696275746573223a5b60801b60c3820152610e5582518093602060d385019101611d88565b01615d7d60f01b60d38201520360b5810184520182611ea2565b610ec2603d60405180937f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000006020830152610eb28151809260208686019101611d88565b810103601d810184520182611ea2565b604051918291602083526020830190611dab565b0390f35b610f0b945091610f699391610ef760469460406000205416612274565b906040519687945180926020870190611d88565b83017f2c7b2274726169745f74797065223a2022436f6c6f7273222c202276616c7565602082015263111d101160e11b6040820152610f54825180936020604485019101611d88565b01906044820152036026810184520182611ea2565b87808080610d20565b604051610f7e81611e6a565b6005815264131a59da1d60da1b6020820152610c97565b60405163677510db60e11b8152600490fd5b3461018757608036600319011261018757610fc0611dd0565b610fc8611de6565b906044356064359267ffffffffffffffff8411610187573660238501121561018757836004013592610ff984611ec4565b936110076040519586611ea2565b808552366024828801011161018757602081600092602461105e99018389013786010152336001600160a01b03821603611082575b61104e611049843361207d565b612536565b6110598383836125f2565b612756565b1561106557005b60405162461bcd60e51b81528061107e60048201612703565b0390fd5b61108b33612923565b61103c565b34610187576040366003190112610187576110a9611dd0565b6024359081151590818303610187576110c181612923565b6001600160a01b03169133831461112f576111019033600052600560205260406000208460005260205260406000209060ff801983541691151516179055565b6040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b60405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606490fd5b34610187576000366003190112610187576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461018757600036600319011261018757604051600060018054906111dd82611faa565b8085529181811690811561125d5750600114611204575b610ed684610ec281860382611ea2565b600081815292507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b828410611245575050508101602001610ec2826111f4565b8054602085870181019190915290930192810161122d565b60ff191660208087019190915292151560051b85019092019250610ec291508390506111f4565b34610187576000366003190112610187576006546040516001600160a01b039091168152602090f35b3461018757602036600319011261018757600435600052600b6020526060604060002061ffff8154169060ff600260018301549201541690604051928352602083015215156040820152f35b3461018757600036600319011261018757611312611ee0565b600680546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610187576020366003190112610187576001600160a01b03611377611dd0565b1680156113965760005260036020526020604060002054604051908152f35b60405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608490fd5b34610187576000366003190112610187576008546040516001600160a01b039091168152602090f35b34610187576020366003190112610187576020611434600435611f84565b6040516001600160a01b039091168152f35b3461018757602036600319011261018757600435611464813361207d565b15611503576009548015610a035760001990810160095560009061148783611f84565b5061149183611f84565b838352600460205260408320906001600160601b0360a01b9182815416905560018060a01b0316918284526003602052604084209081540190558383526002602052604083209081541690557fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a4005b60405163390cdd9b60e21b8152600490fd5b346101875761105e61152636611dfc565b6001600160a01b038316331415929091908361155f575b6040519361154a85611e31565b600085526110825761104e611049843361207d565b61156833612923565b61153d565b346101875760003660031901126101875760206040516daaeb6d7670e522a718067333cd4e8152f35b34610187576020366003190112610187576115af611dd0565b6115b7611ee0565b600854906001600160a01b03908183166115f557169081156115e3576001600160a01b03191617600855005b60405163022750fb60e31b8152600490fd5b604051631b7d42d760e11b8152600490fd5b3461018757602036600319011261018757600435611625813361207d565b15611503576000818152600b60209081526040909120600201805460ff818116151660ff199091161790557ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce791604051908152a1005b34610187576020366003190112610187576001600160a01b0361169c611dd0565b16600052600c602052602060ff604060002054166040519015158152f35b3461018757604036600319011261018757600435600090815260026020526040902054602435906001600160a01b031615610f955760018060a01b0360065416601982029180830460191490151715610a03576103e86040928351928352046020820152f35b346101875761175561173136611dfc565b91336001600160a01b03821603611757575b611750611049843361207d565b6125f2565b005b61176033612923565b611743565b34610187576000366003190112610187576020600954604051908152f35b34610187576000366003190112610187576007544211611a0b57336000526020600c815260ff604060002054166119f9576117bf600a54612022565b9081600a556117ed7f000000000000000000000000000000000000000000000000000000000000000061287b565b6118167f000000000000000000000000000000000000000000000000000000000000000061287b565b8101809111610a035760085461ffff9182169082906001600160a01b0316806119e0575b5081168061195c575b50505033600052600c81526040600020600160ff19825416179055611869600954612022565b60095533156119195760029061189d61189784600052600260205260018060a01b0360406000205416151590565b15612031565b6000838152600260205260409020546118c0906001600160a01b03161515611897565b336000526003815260406000206001815401905582600052526040600020336001600160601b0360a01b8254161790553360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4005b6064906040519062461bcd60e51b825280600483015260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152fd5b605111156119d757905b83600052600b83526040600020911661ffff19825416179055600954604051828101913360601b83524160601b60348301526048820152604881526080810181811067ffffffffffffffff82111761096f5760405251902082600052600b8252600160406000200155828080611843565b50605090611966565b6119e99061287b565b1601818111610a0357818561183a565b604051631bbdf5c560e31b8152600490fd5b604051633d20ce7960e21b8152600490fd5b34610187576000366003190112610187576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461018757604036600319011261018757611a7b611dd0565b60243590611a8881612923565b6001600160a01b038080611a9b85611f84565b16921691808314611b9657803314908115611b71575b5015611b0657600083815260046020526040902080546001600160a01b03191683179055611ade83611f84565b167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a4005b60405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608490fd5b9050600052600560205260406000203360005260205260ff6040600020541684611ab1565b60405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608490fd5b34610187576000366003190112610187576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610187576020366003190112610187576020611434600435611fe4565b346101875760003660031901126101875760405160008054611c6981611faa565b8084529060019081811690811561125d5750600114611c9257610ed684610ec281860382611ea2565b600080805292507f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b828410611cd3575050508101602001610ec2826111f4565b80546020858701810191909152909301928101611cbb565b34610187576020366003190112610187576004359063ffffffff60e01b82168092036101875760209163152a902d60e11b8114908115611d77575b8115611d34575b5015158152f35b6380ac58cd60e01b811491508115611d66575b8115611d55575b5083611d2d565b6301ffc9a760e01b14905083611d4e565b635b5e139f60e01b81149150611d47565b632483248360e11b81149150611d26565b60005b838110611d9b5750506000910152565b8181015183820152602001611d8b565b90602091611dc481518092818552858086019101611d88565b601f01601f1916010190565b600435906001600160a01b038216820361018757565b602435906001600160a01b038216820361018757565b6060906003190112610187576001600160a01b0390600435828116810361018757916024359081168103610187579060443590565b6020810190811067ffffffffffffffff82111761096f57604052565b610a00810190811067ffffffffffffffff82111761096f57604052565b6040810190811067ffffffffffffffff82111761096f57604052565b60a0810190811067ffffffffffffffff82111761096f57604052565b90601f8019910116810190811067ffffffffffffffff82111761096f57604052565b67ffffffffffffffff811161096f57601f01601f191660200190565b6006546001600160a01b03163303611ef457565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b15611f3f57565b60405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606490fd5b6000908152600260205260409020546001600160a01b0316611fa7811515611f38565b90565b90600182811c92168015611fda575b6020831014611fc457565b634e487b7160e01b600052602260045260246000fd5b91607f1691611fb9565b600081815260026020526040902054612007906001600160a01b03161515611f38565b6000908152600460205260409020546001600160a01b031690565b6000198114610a035760010190565b1561203857565b60405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606490fd5b906001600160a01b03808061209184611f84565b169316918383149384156120c4575b5083156120ae575b50505090565b6120ba91929350611fe4565b16143880806120a8565b909350600052600560205260406000208260005260205260ff6040600020541692386120a0565b906120f582611ec4565b6121026040519182611ea2565b8281528092612113601f1991611ec4565b0190602036910137565b805115612260576040516060810181811067ffffffffffffffff82111761096f57604052604081527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f60408201528151600292838201809211610a03576003918290046001600160fe1b0381168103610a03576121c3908594951b6120eb565b936020850193829183518401925b83811061220f57505050505106806001146121fc576002146121f1575090565b603d90600019015390565b50603d9081600019820153600119015390565b85600491979293949701918251600190603f9082828260121c16880101518453828282600c1c16880101518385015382828260061c16880101518885015316850101518782015301959291906121d1565b5060405161226d81611e31565b6000815290565b806000917a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000808210156123a9575b506d04ee2d6d415b85acef81000000008083101561239a575b50662386f26fc100008083101561238b575b506305f5e1008083101561237c575b506127108083101561236d575b50606482101561235d575b600a80921015612353575b60019081602161230b8287016120eb565b95860101905b61231d575b5050505090565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a83530491821561234e57919082612311565b612316565b91600101916122fa565b91906064600291049101916122ef565b600491939204910191386122e4565b600891939204910191386122d7565b601091939204910191386122c8565b602091939204910191386122b6565b60409350810491503861229d565b600052600b60205260ff6002604060002001541661247a576040516123db81611e86565b607e81527f3c7061746820643d274d32303030203048305632303030483230303056305a2760208201527f2066696c6c3d2723656665666566272f3e3c7061746820643d274d313434382e60408201527f3839203434372e383532483535312e31303756313535322e313548313434382e60608201527f3839563434372e3835325a272066696c6c3d272366666666666627202f3e0000608082015290565b60405161248681611e86565b607e81527f3c7061746820643d274d32303030203048305632303030483230303056305a2760208201527f2066696c6c3d2723303030303030272f3e3c7061746820643d274d313434382e60408201527f3839203434372e383532483535312e31303756313535322e313548313434382e60608201527f3839563434372e3835325a272066696c6c3d272331313131313127202f3e0000608082015290565b9060508110156107295760051b0190565b1561253d57565b60405162461bcd60e51b815260206004820152602d60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201526c1c881bdc88185c1c1c9bdd9959609a1b6064820152608490fd5b1561259f57565b60405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608490fd5b9061261a9161260084611f84565b6001600160a01b0393918416928492909183168414612598565b169182156126b257816126379161263086611f84565b1614612598565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60008481526004602052604081206001600160601b0360a01b9081815416905583825260036020526040822060001981540190558482526040822060018154019055858252600260205284604083209182541617905580a4565b60405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b60809060208152603260208201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b60608201520190565b9293600093909291803b15612870579484916127b09660405180948193630a85bd0160e11b9788845233600485015260018060a01b0380921660248501526044840152608060648401528260209b8c976084830190611dab565b0393165af184918161282c575b5061281b575050503d600014612813573d6127d781611ec4565b906127e56040519283611ea2565b81528091833d92013e5b805191826128105760405162461bcd60e51b81528061107e60048201612703565b01fd5b5060606127ef565b6001600160e01b0319161492509050565b9091508581813d8311612869575b6128448183611ea2565b8101031261286557516001600160e01b0319811681036128655790386127bd565b8480fd5b503d61283a565b505050915050600190565b604051633de222bb60e21b81526001600160a01b039091166004820152336024820152602081806044810103817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115612917576000916128e6575090565b906020823d821161290f575b816128ff60209383611ea2565b8101031261290c57505190565b80fd5b3d91506128f2565b6040513d6000823e3d90fd5b6daaeb6d7670e522a718067333cd4e803b61293c575050565b604051633185c44d60e21b81523060048201526001600160a01b038316602482015290602090829060449082905afa908115612917576000916129a5575b50156129835750565b604051633b79c77360e21b81526001600160a01b039091166004820152602490fd5b6020813d82116129db575b816129bd60209383611ea2565b810103126129d7575190811515820361290c57503861297a565b5080fd5b3d91506129b056fea2646970667358221220b79c97330278fc89a1df5625b96a51114b36b194edf3eba9f4a336a741fb9d5364736f6c63430008110033b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60000000000000000000000000000000000000000000000000000000063e647420000000000000000000000006fe0b5c1ba36c79d9d7dd43f60a3e53e3699c8c000000000000000000000000034eebee6942d8def3c125458d1a86e0a897fd6f9000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c
Deployed Bytecode
0x608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a714611ceb5750806306fdde0314611c48578063081812fc14611c2a5780630869806e14611be5578063095ea7b314611a6257806310fef2da14611a1d5780631249c58b1461178357806318160ddd1461176557806323b872dd146117205780632a55205a146116ba57806338e21cce1461167b5780633d317ed01461160757806340de28291461159657806341f434341461156d57806342842e0e1461151557806342966c68146114465780636352211e14611416578063685eca95146113ed57806370a0823114611356578063715018a6146112f95780638d899ea4146112ad5780638da5cb5b1461128457806395d89b41146111b9578063a085048714611174578063a22cb46514611090578063b88d4fde14610fa7578063c87b56dd146102a6578063e985e9c514610250578063f2fde38b1461018c5763fcfae6081461016957600080fd5b34610187576000366003190112610187576020600754604051908152f35b600080fd5b34610187576020366003190112610187576101a5611dd0565b6101ad611ee0565b6001600160a01b039081169081156101fc57600654826001600160601b0360a01b821617600655167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b3461018757604036600319011261018757610269611dd0565b610271611de6565b9060018060a01b03809116600052600560205260406000209116600052602052602060ff604060002054166040519015158152f35b34610187576020366003190112610187576004356000908152600260205260409020546001600160a01b031615610f95576102e2600435612274565b6102ed6004356123b7565b60009160605b605060ff85161015610ba557610a0060405161030e81611e4d565b36903760405180605d60005b6050601f820110610a19575060ff6101e091548181168452818160081c166020850152818160101c166040850152818160181c166060850152818160201c166080850152818160281c1660a0850152818160301c1660c0850152818160381c1660e0850152818160401c16610100850152818160481c16610120850152818160501c16610140850152818160581c16610160850152818160601c16610180850152818160681c166101a0850152818160701c166101c085015260781c169101526103e381611e4d565b60005b6050811061098c57506004356000908152600b602052604090205461ffff16156109855761041960ff9182871690612525565b51165b600435600052600b60205261ffff6040600020541660ff86161060001461073f57605081101561072957606001549061046661ffff61045c818516612274565b9360101c16612274565b600435600052600b60205260ff605081600160406000200154818a161c160616605081101561072957600d0190604051917f3c7061746820643d274d302e38393330303520302e3839373934394833352e3060208401527f39334c33352e3039332031322e3239384834362e3439335634362e343938483360408401527f352e3039334c33352e3039332035372e3839373948302e38393330303556302e60608401526e3839373934395a272066696c6c3d2760881b608084015260009080549061053082611faa565b916001811690811561070457506001146106c9575b505060019383631e17b39f60e11b6106bf9461061a608c60ff9a98877f27202f3e3c7061746820643d274d33352e3039332031322e3239384831322e32604099527f39335633352e3039384833352e3039335631322e3239385a272066696c6c3d2760208201527f2366666666666627202f3e3c7061746820643d274d33352e312032332e363938898201527f4832332e375633352e3039384833352e315632332e3639385a272066696c6c3d60608201526b13919818181818181390179f60a11b608082015203606c810186520184611ea2565b6214939f60e91b855197856106398a975180926020808b019101611d88565b860177078ce40e8e4c2dce6ccdee4da7a4ee8e4c2dce6d8c2e8ca560431b6020820152610670825180936020603885019101611d88565b01600160fd1b60388201528251906106918260399560208785019101611d88565b01918201528251906106ac82603c9560208785019101611d88565b0191820152036020810184520182611ea2565b945b0116926102f3565b90915060005260206000206000905b8282106106ed5750508201608f018383610545565b60018160209254608f8589010152019101906106d8565b60ff1916608f8088019190915283151590930286019092019250859150849050610545565b634e487b7160e01b600052603260045260246000fd5b605081101561072957606001549061075e61ffff61045c818516612274565b916040518061014081011067ffffffffffffffff6101408301111761096f57604060019382631e17b39f60e11b60ff9761014061096996018552610102835260208301927f3c7061746820643d274d302e38393330303520302e3839373934394833352e3084527f39334c33352e3039332031322e3239384834362e3439335634362e3439384833868201527f352e3039334c33352e3039332035372e3839373948302e38393330303556302e60608201527f3839373934395a272066696c6c3d272336356263343827202f3e3c706174682060808201527f643d274d33352e3039332031322e3239384831322e3239335633352e3039384860a08201527f33352e3039335631322e3239385a272066696c6c3d272366666666666627202f60c08201527f3e3c7061746820643d274d33352e312032332e3639384832332e375633352e3060e08201527f39384833352e315632332e3639385a272066696c6c3d2723303030303030272061010082015261179f60f11b6101208201526214939f60e91b865198866108fa8b985180926020808c019101611d88565b870177078ce40e8e4c2dce6ccdee4da7a4ee8e4c2dce6d8c2e8ca560431b6020820152610931825180936020603885019101611d88565b01600160fd1b60388201528351906109528260399660208885019101611d88565b019283015251906106ac82603c9586840190611d88565b946106c1565b634e487b7160e01b600052604160045260246000fd5b508361041c565b600435600052600b602052600190816040600020015491810191828211610a035782156109ed57826109e7910660ff6109c58487612525565b5116926109e060ff6109d78489612525565b51169187612525565b5284612525565b526103e6565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b90916001610400602092855460ff8116825260ff8160081c168583015260ff8160101c16604083015260ff8160181c16606083015260ff8160808282891c1681860152828260a0828260281c1681890152828260c095828260301c16878c0152828260381c1660e08c0152828260401c166101008c0152828260481c166101208c0152828260501c166101408c0152828260581c166101608c0152828260601c166101808c0152828260681c166101a08c0152828260701c166101c08c0152828260781c166101e08c01521c16610200890152828260881c16610220890152828260901c16610240890152828260981c166102608901521c16610280860152828260a81c166102a0860152828260b01c166102c0860152828260b81c166102e08601521c1661030083015260ff8160c81c1661032083015260ff8160d01c1661034083015260ff8160d81c1661036083015260ff8160e01c1661038083015260ff8160e81c166103a083015260ff8160f01c166103c083015260f81c6103e0820152019301910161031a565b90610c5560d5610c5a610e6f94610c556066610ed6986040519384917f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323060208401527f30302f737667272076696577426f783d2730203020323030302032303030273e6040840152610c21815180926020606087019101611d88565b8201610c37825180936020606085019101611d88565b01651e17b9bb339f60d11b6060820152036046810184520182611ea2565b61211d565b92600435600052600b60205260ff60026040600020015416600014610f7257604051610c8581611e6a565b60048152634461726b60e01b60208201525b60405160208101917f7b2274726169745f74797065223a20224d6f6465222c202276616c7565223a208352601160f91b6040830152610ce0815180926020604186019101611d88565b8101610d0360438361227d60f01b93846041820152036023810185520183611ea2565b8192600435600052600b60205261ffff8060406000205416610eda575b505050506040519485927f7b226e616d65223a2022436865636b20547572747a20230000000000000000006020850152610d64815180926020603788019101611d88565b83017f222c20226465736372697074696f6e223a2022436865636b20547572747a206960378201527f7320612066756c6c79206f6e2d636861696e2c2067616d69666965642054696e60578201527f792057696e67656420547572746c657a207820436865636b732064657269766160778201527f746976652e222c2022696d616765223a2022646174613a696d6167652f73766760978201526b0ade1b5b0ed8985cd94d8d0b60a21b60b7820152610e2782518093602060c385019101611d88565b016f222c2261747472696275746573223a5b60801b60c3820152610e5582518093602060d385019101611d88565b01615d7d60f01b60d38201520360b5810184520182611ea2565b610ec2603d60405180937f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000006020830152610eb28151809260208686019101611d88565b810103601d810184520182611ea2565b604051918291602083526020830190611dab565b0390f35b610f0b945091610f699391610ef760469460406000205416612274565b906040519687945180926020870190611d88565b83017f2c7b2274726169745f74797065223a2022436f6c6f7273222c202276616c7565602082015263111d101160e11b6040820152610f54825180936020604485019101611d88565b01906044820152036026810184520182611ea2565b87808080610d20565b604051610f7e81611e6a565b6005815264131a59da1d60da1b6020820152610c97565b60405163677510db60e11b8152600490fd5b3461018757608036600319011261018757610fc0611dd0565b610fc8611de6565b906044356064359267ffffffffffffffff8411610187573660238501121561018757836004013592610ff984611ec4565b936110076040519586611ea2565b808552366024828801011161018757602081600092602461105e99018389013786010152336001600160a01b03821603611082575b61104e611049843361207d565b612536565b6110598383836125f2565b612756565b1561106557005b60405162461bcd60e51b81528061107e60048201612703565b0390fd5b61108b33612923565b61103c565b34610187576040366003190112610187576110a9611dd0565b6024359081151590818303610187576110c181612923565b6001600160a01b03169133831461112f576111019033600052600560205260406000208460005260205260406000209060ff801983541691151516179055565b6040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b60405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606490fd5b34610187576000366003190112610187576040517f000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c6001600160a01b03168152602090f35b3461018757600036600319011261018757604051600060018054906111dd82611faa565b8085529181811690811561125d5750600114611204575b610ed684610ec281860382611ea2565b600081815292507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b828410611245575050508101602001610ec2826111f4565b8054602085870181019190915290930192810161122d565b60ff191660208087019190915292151560051b85019092019250610ec291508390506111f4565b34610187576000366003190112610187576006546040516001600160a01b039091168152602090f35b3461018757602036600319011261018757600435600052600b6020526060604060002061ffff8154169060ff600260018301549201541690604051928352602083015215156040820152f35b3461018757600036600319011261018757611312611ee0565b600680546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610187576020366003190112610187576001600160a01b03611377611dd0565b1680156113965760005260036020526020604060002054604051908152f35b60405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608490fd5b34610187576000366003190112610187576008546040516001600160a01b039091168152602090f35b34610187576020366003190112610187576020611434600435611f84565b6040516001600160a01b039091168152f35b3461018757602036600319011261018757600435611464813361207d565b15611503576009548015610a035760001990810160095560009061148783611f84565b5061149183611f84565b838352600460205260408320906001600160601b0360a01b9182815416905560018060a01b0316918284526003602052604084209081540190558383526002602052604083209081541690557fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a4005b60405163390cdd9b60e21b8152600490fd5b346101875761105e61152636611dfc565b6001600160a01b038316331415929091908361155f575b6040519361154a85611e31565b600085526110825761104e611049843361207d565b61156833612923565b61153d565b346101875760003660031901126101875760206040516daaeb6d7670e522a718067333cd4e8152f35b34610187576020366003190112610187576115af611dd0565b6115b7611ee0565b600854906001600160a01b03908183166115f557169081156115e3576001600160a01b03191617600855005b60405163022750fb60e31b8152600490fd5b604051631b7d42d760e11b8152600490fd5b3461018757602036600319011261018757600435611625813361207d565b15611503576000818152600b60209081526040909120600201805460ff818116151660ff199091161790557ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce791604051908152a1005b34610187576020366003190112610187576001600160a01b0361169c611dd0565b16600052600c602052602060ff604060002054166040519015158152f35b3461018757604036600319011261018757600435600090815260026020526040902054602435906001600160a01b031615610f955760018060a01b0360065416601982029180830460191490151715610a03576103e86040928351928352046020820152f35b346101875761175561173136611dfc565b91336001600160a01b03821603611757575b611750611049843361207d565b6125f2565b005b61176033612923565b611743565b34610187576000366003190112610187576020600954604051908152f35b34610187576000366003190112610187576007544211611a0b57336000526020600c815260ff604060002054166119f9576117bf600a54612022565b9081600a556117ed7f0000000000000000000000006fe0b5c1ba36c79d9d7dd43f60a3e53e3699c8c061287b565b6118167f00000000000000000000000034eebee6942d8def3c125458d1a86e0a897fd6f961287b565b8101809111610a035760085461ffff9182169082906001600160a01b0316806119e0575b5081168061195c575b50505033600052600c81526040600020600160ff19825416179055611869600954612022565b60095533156119195760029061189d61189784600052600260205260018060a01b0360406000205416151590565b15612031565b6000838152600260205260409020546118c0906001600160a01b03161515611897565b336000526003815260406000206001815401905582600052526040600020336001600160601b0360a01b8254161790553360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4005b6064906040519062461bcd60e51b825280600483015260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152fd5b605111156119d757905b83600052600b83526040600020911661ffff19825416179055600954604051828101913360601b83524160601b60348301526048820152604881526080810181811067ffffffffffffffff82111761096f5760405251902082600052600b8252600160406000200155828080611843565b50605090611966565b6119e99061287b565b1601818111610a0357818561183a565b604051631bbdf5c560e31b8152600490fd5b604051633d20ce7960e21b8152600490fd5b34610187576000366003190112610187576040517f0000000000000000000000006fe0b5c1ba36c79d9d7dd43f60a3e53e3699c8c06001600160a01b03168152602090f35b3461018757604036600319011261018757611a7b611dd0565b60243590611a8881612923565b6001600160a01b038080611a9b85611f84565b16921691808314611b9657803314908115611b71575b5015611b0657600083815260046020526040902080546001600160a01b03191683179055611ade83611f84565b167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a4005b60405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608490fd5b9050600052600560205260406000203360005260205260ff6040600020541684611ab1565b60405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608490fd5b34610187576000366003190112610187576040517f00000000000000000000000034eebee6942d8def3c125458d1a86e0a897fd6f96001600160a01b03168152602090f35b34610187576020366003190112610187576020611434600435611fe4565b346101875760003660031901126101875760405160008054611c6981611faa565b8084529060019081811690811561125d5750600114611c9257610ed684610ec281860382611ea2565b600080805292507f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b828410611cd3575050508101602001610ec2826111f4565b80546020858701810191909152909301928101611cbb565b34610187576020366003190112610187576004359063ffffffff60e01b82168092036101875760209163152a902d60e11b8114908115611d77575b8115611d34575b5015158152f35b6380ac58cd60e01b811491508115611d66575b8115611d55575b5083611d2d565b6301ffc9a760e01b14905083611d4e565b635b5e139f60e01b81149150611d47565b632483248360e11b81149150611d26565b60005b838110611d9b5750506000910152565b8181015183820152602001611d8b565b90602091611dc481518092818552858086019101611d88565b601f01601f1916010190565b600435906001600160a01b038216820361018757565b602435906001600160a01b038216820361018757565b6060906003190112610187576001600160a01b0390600435828116810361018757916024359081168103610187579060443590565b6020810190811067ffffffffffffffff82111761096f57604052565b610a00810190811067ffffffffffffffff82111761096f57604052565b6040810190811067ffffffffffffffff82111761096f57604052565b60a0810190811067ffffffffffffffff82111761096f57604052565b90601f8019910116810190811067ffffffffffffffff82111761096f57604052565b67ffffffffffffffff811161096f57601f01601f191660200190565b6006546001600160a01b03163303611ef457565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b15611f3f57565b60405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606490fd5b6000908152600260205260409020546001600160a01b0316611fa7811515611f38565b90565b90600182811c92168015611fda575b6020831014611fc457565b634e487b7160e01b600052602260045260246000fd5b91607f1691611fb9565b600081815260026020526040902054612007906001600160a01b03161515611f38565b6000908152600460205260409020546001600160a01b031690565b6000198114610a035760010190565b1561203857565b60405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606490fd5b906001600160a01b03808061209184611f84565b169316918383149384156120c4575b5083156120ae575b50505090565b6120ba91929350611fe4565b16143880806120a8565b909350600052600560205260406000208260005260205260ff6040600020541692386120a0565b906120f582611ec4565b6121026040519182611ea2565b8281528092612113601f1991611ec4565b0190602036910137565b805115612260576040516060810181811067ffffffffffffffff82111761096f57604052604081527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f60408201528151600292838201809211610a03576003918290046001600160fe1b0381168103610a03576121c3908594951b6120eb565b936020850193829183518401925b83811061220f57505050505106806001146121fc576002146121f1575090565b603d90600019015390565b50603d9081600019820153600119015390565b85600491979293949701918251600190603f9082828260121c16880101518453828282600c1c16880101518385015382828260061c16880101518885015316850101518782015301959291906121d1565b5060405161226d81611e31565b6000815290565b806000917a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000808210156123a9575b506d04ee2d6d415b85acef81000000008083101561239a575b50662386f26fc100008083101561238b575b506305f5e1008083101561237c575b506127108083101561236d575b50606482101561235d575b600a80921015612353575b60019081602161230b8287016120eb565b95860101905b61231d575b5050505090565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a83530491821561234e57919082612311565b612316565b91600101916122fa565b91906064600291049101916122ef565b600491939204910191386122e4565b600891939204910191386122d7565b601091939204910191386122c8565b602091939204910191386122b6565b60409350810491503861229d565b600052600b60205260ff6002604060002001541661247a576040516123db81611e86565b607e81527f3c7061746820643d274d32303030203048305632303030483230303056305a2760208201527f2066696c6c3d2723656665666566272f3e3c7061746820643d274d313434382e60408201527f3839203434372e383532483535312e31303756313535322e313548313434382e60608201527f3839563434372e3835325a272066696c6c3d272366666666666627202f3e0000608082015290565b60405161248681611e86565b607e81527f3c7061746820643d274d32303030203048305632303030483230303056305a2760208201527f2066696c6c3d2723303030303030272f3e3c7061746820643d274d313434382e60408201527f3839203434372e383532483535312e31303756313535322e313548313434382e60608201527f3839563434372e3835325a272066696c6c3d272331313131313127202f3e0000608082015290565b9060508110156107295760051b0190565b1561253d57565b60405162461bcd60e51b815260206004820152602d60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201526c1c881bdc88185c1c1c9bdd9959609a1b6064820152608490fd5b1561259f57565b60405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608490fd5b9061261a9161260084611f84565b6001600160a01b0393918416928492909183168414612598565b169182156126b257816126379161263086611f84565b1614612598565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60008481526004602052604081206001600160601b0360a01b9081815416905583825260036020526040822060001981540190558482526040822060018154019055858252600260205284604083209182541617905580a4565b60405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b60809060208152603260208201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b60608201520190565b9293600093909291803b15612870579484916127b09660405180948193630a85bd0160e11b9788845233600485015260018060a01b0380921660248501526044840152608060648401528260209b8c976084830190611dab565b0393165af184918161282c575b5061281b575050503d600014612813573d6127d781611ec4565b906127e56040519283611ea2565b81528091833d92013e5b805191826128105760405162461bcd60e51b81528061107e60048201612703565b01fd5b5060606127ef565b6001600160e01b0319161492509050565b9091508581813d8311612869575b6128448183611ea2565b8101031261286557516001600160e01b0319811681036128655790386127bd565b8480fd5b503d61283a565b505050915050600190565b604051633de222bb60e21b81526001600160a01b039091166004820152336024820152602081806044810103817f000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c6001600160a01b03165afa908115612917576000916128e6575090565b906020823d821161290f575b816128ff60209383611ea2565b8101031261290c57505190565b80fd5b3d91506128f2565b6040513d6000823e3d90fd5b6daaeb6d7670e522a718067333cd4e803b61293c575050565b604051633185c44d60e21b81523060048201526001600160a01b038316602482015290602090829060449082905afa908115612917576000916129a5575b50156129835750565b604051633b79c77360e21b81526001600160a01b039091166004820152602490fd5b6020813d82116129db575b816129bd60209383611ea2565b810103126129d7575190811515820361290c57503861297a565b5080fd5b3d91506129b056fea2646970667358221220b79c97330278fc89a1df5625b96a51114b36b194edf3eba9f4a336a741fb9d5364736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000063e647420000000000000000000000006fe0b5c1ba36c79d9d7dd43f60a3e53e3699c8c000000000000000000000000034eebee6942d8def3c125458d1a86e0a897fd6f9000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c
-----Decoded View---------------
Arg [0] : _mintEnds (uint256): 1676035906
Arg [1] : _twtAddress (address): 0x6fE0b5c1ba36C79D9D7dD43f60a3e53E3699C8C0
Arg [2] : _checksAddress (address): 0x34eEBEE6942d8Def3c125458D1a86e0A897fd6f9
Arg [3] : _warmWalletAddress (address): 0xC3AA9bc72Bd623168860a1e5c6a4530d3D80456c
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000063e64742
Arg [1] : 0000000000000000000000006fe0b5c1ba36c79d9d7dd43f60a3e53e3699c8c0
Arg [2] : 00000000000000000000000034eebee6942d8def3c125458d1a86e0a897fd6f9
Arg [3] : 000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c
Loading...
Loading
Loading...
Loading
OVERVIEW
Check Turtz is a fully on-chain, gamified Tiny Winged Turtlez x Checks derivative.Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.