ERC-721
Overview
Max Total Supply
0 FIG
Holders
19
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
3 FIGLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
FiguresToken
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 5 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; import "./IFiguresToken.sol"; import "./FiguresSingles.sol"; import "./FiguresDoubles.sol"; import "./FiguresRenderLib.sol"; import "@manifoldxyz/creator-core-solidity/contracts/ERC721Creator.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; contract FiguresToken is ERC721Creator, IFiguresToken { using Counters for Counters.Counter; address public CONTROLLER_ADDRESS; string private _baseSvg = ""; uint256 private _scaleFactor = 20; string[3] private _backgroundColors = [ "255,120,211", "255,227,0", "25,180,255" ]; struct RandomVariables { uint8 number; uint8[4] bgColor1Index; uint8[4] bgColor2Index; uint8 figureIndex1_1; uint8 figureIndex1_2; uint8 figureIndex2_1; uint8 figureIndex2_2; } mapping(uint256 => uint256) private _seeds; mapping(uint256 => RandomVariables) private _seedRandom; constructor() ERC721Creator("Figures", "FIG") {} function setControllerAddress( address controllerAddress ) external onlyOwner { CONTROLLER_ADDRESS = controllerAddress; } function getControllerAddress() public view returns (address) { return CONTROLLER_ADDRESS; } function withdrawETH(uint256 amount) public onlyOwner { payable(msg.sender).transfer(amount); } /** * @dev See {IFiguresToken-initializeSeed}. */ function initializeSeed(uint256[] memory seed) external override { require(msg.sender == CONTROLLER_ADDRESS, "Permission denied"); // generate all the random numbers you need here! _seedRandom[seed[0]] = RandomVariables({ number: uint8(_random(100, seed[0])), bgColor1Index: [ uint8(_random(20, seed[1])), uint8(_random(20, seed[2])), uint8(_random(20, seed[3])), uint8(_random(20, seed[4])) ], bgColor2Index: [ uint8(_random(20, seed[5])), uint8(_random(20, seed[6])), uint8(_random(20, seed[7])), uint8(_random(20, seed[8])) ], // 360 is the max number of options for number '9' figureIndex1_1: uint8(_random(360, seed[9])), figureIndex1_2: uint8(_random(360, seed[10])), figureIndex2_1: uint8(_random(360, seed[11])), figureIndex2_2: uint8(_random(360, seed[12])) }); } /** * @dev See {IFiguresToken-mint}. */ function mint( uint256 tokenId, uint256 seed, address recipient ) external override { require(msg.sender == CONTROLLER_ADDRESS, "Permission denied"); // Store render data for this token _seeds[tokenId] = seed; // Mint token _mint(recipient, tokenId); } /** * @dev See {IERC721-tokenURI}. */ function tokenURI( uint256 tokenId ) public view override returns (string memory) { _requireMinted(tokenId); return render(_seeds[tokenId], tokenId); } function tokenNumber( uint256 tokenId ) public view returns (uint8) { _requireMinted(tokenId); return _seedRandom[_seeds[tokenId]].number; } /** * @dev See {IFiguresToken-render}. */ function render( uint256 seed, uint256 assetId ) public view override returns (string memory) { uint256 n; string memory s; string memory attributes; RandomVariables memory variables = _seedRandom[seed]; n = variables.number; s = _concat(s, "data:image/svg+xml;utf8,"); s = _concat( s, "<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' id='figures' width='" ); s = _concat(s, Strings.toString(10 * _scaleFactor)); s = _concat(s, "' height='"); s = _concat(s, Strings.toString(10 * _scaleFactor)); s = _concat(s, "'>"); s = _concat( s, _drawBackground(variables.bgColor1Index, variables.bgColor2Index) ); if (n < 10) { bool[][2] memory figArrays = FiguresSingles.chooseStringsSingles( uint8(n), variables.figureIndex1_1, variables.figureIndex1_2 ); s = _concat( s, _drawFigure( false, figArrays ) ); } else { uint8 leftNumber = uint8(n / 10); uint8 rightNumber = uint8(n % 10); bool[][2] memory figArraysLeft = FiguresDoubles.chooseStringsDoubles( leftNumber, variables.figureIndex1_1, variables.figureIndex1_2 ); bool[][2] memory figArraysRight = FiguresDoubles.chooseStringsDoubles( rightNumber, variables.figureIndex2_1, variables.figureIndex2_2 ); s = _concat( s, _drawFigure( false, figArraysLeft ) ); s = _concat( s, _drawFigure( true, figArraysRight ) ); } s = _concat(s, "</svg>"); attributes = _concat('{"name":"Figure #', Strings.toString(assetId)); attributes = _concat(attributes, '", "description":"Figure representation of '); attributes = _concat(attributes, Strings.toString(n)); attributes = _concat(attributes, '.", "created_by":"Figures", "external_url":"https://figures.art/token/'); attributes = _concat(attributes, Strings.toString(assetId)); attributes = _concat(attributes, '", "attributes": [{"trait_type": "Number", "value":"'); attributes = _concat(attributes, Strings.toString(n)); attributes = _concat(attributes, '"}], "image":"'); return string( abi.encodePacked( 'data:application/json;utf8,', attributes, s, '"}' ) ); } function _random( uint256 number, uint256 count ) internal view returns (uint256) { return uint256( keccak256( abi.encodePacked( block.timestamp, block.difficulty, msg.sender, count ) ) ) % number; } function _concat(string memory a, string memory b) private pure returns (string memory) { return string(abi.encodePacked(a, b)); } function _drawBackground( uint8[4] memory bgColor1Index, uint8[4] memory bgColor2Index ) internal view returns (string memory) { // Draw first layer of bg by laying 4 randomly colored tiled string memory s = ""; for (uint256 i = 0; i < 4; i++) { uint bgColor1IndexAvailable = bgColor1Index[i] % 3; uint bgColor2IndexAvailable = bgColor2Index[i] % 4; s = _concat(s, "<g>"); s = _concat( s, ( FiguresRenderLib._generateRect( (i % 2) * uint256(5) * _scaleFactor, (i / 2) * uint256(5) * _scaleFactor, uint256(5) * _scaleFactor, uint256(5) * _scaleFactor, _backgroundColors[bgColor1IndexAvailable], "" ) ) ); if (bgColor2IndexAvailable == 3) { s = _concat(s, "</g>"); continue; } s = _concat( s, ( FiguresRenderLib._generateRect( (i % 2) * uint256(5) * _scaleFactor, (i / 2) * uint256(5) * _scaleFactor, uint256(5) * _scaleFactor, uint256(5) * _scaleFactor, _backgroundColors[bgColor2IndexAvailable], "mix-blend-mode: multiply;" ) ) ); s = _concat(s, "</g>"); } return s; } function _drawFigure( bool rightOffset, bool[][2] memory figArrays ) internal view returns (string memory) { uint256 rightOffsetX = 0; if (rightOffset) { rightOffsetX = uint256(5) * _scaleFactor; } string memory s = ""; // k is top and bottom for (uint256 k = 0; k < 2; k++) { // i is each pixel for (uint256 i = 0; i < figArrays[k].length; ++i) { uint8 size = uint8(figArrays[k].length / 5); if (figArrays[k][i]) { continue; } uint256 xOffset = _scaleFactor; uint256 yOffset = _scaleFactor; uint256 x = (i % size) * xOffset + rightOffsetX; uint256 y = 0; if (k == 1) { y = (5 * yOffset); } y += (i / size) * yOffset; s = _concat(s, FiguresRenderLib._generatePixelSVG(x, y, _scaleFactor, "255,120,211")); } } return s; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "../extensions/ICreatorExtensionTokenURI.sol"; import "../extensions/ICreatorExtensionRoyalties.sol"; import "./ICreatorCore.sol"; /** * @dev Core creator implementation */ abstract contract CreatorCore is ReentrancyGuard, ICreatorCore, ERC165 { using Strings for uint256; using EnumerableSet for EnumerableSet.AddressSet; using AddressUpgradeable for address; uint256 internal _tokenCount = 0; // Base approve transfers address location address internal _approveTransferBase; // Track registered extensions data EnumerableSet.AddressSet internal _extensions; EnumerableSet.AddressSet internal _blacklistedExtensions; mapping (address => address) internal _extensionPermissions; mapping (address => bool) internal _extensionApproveTransfers; // For tracking which extension a token was minted by mapping (uint256 => address) internal _tokensExtension; // The baseURI for a given extension mapping (address => string) private _extensionBaseURI; mapping (address => bool) private _extensionBaseURIIdentical; // The prefix for any tokens with a uri configured mapping (address => string) private _extensionURIPrefix; // Mapping for individual token URIs mapping (uint256 => string) internal _tokenURIs; // Royalty configurations struct RoyaltyConfig { address payable receiver; uint16 bps; } mapping (address => RoyaltyConfig[]) internal _extensionRoyalty; mapping (uint256 => RoyaltyConfig[]) internal _tokenRoyalty; bytes4 private constant _CREATOR_CORE_V1 = 0x28f10a21; /** * External interface identifiers for royalties */ /** * @dev CreatorCore * * bytes4(keccak256('getRoyalties(uint256)')) == 0xbb3bafd6 * * => 0xbb3bafd6 = 0xbb3bafd6 */ bytes4 private constant _INTERFACE_ID_ROYALTIES_CREATORCORE = 0xbb3bafd6; /** * @dev Rarible: RoyaltiesV1 * * bytes4(keccak256('getFeeRecipients(uint256)')) == 0xb9c4d9fb * bytes4(keccak256('getFeeBps(uint256)')) == 0x0ebd4c7f * * => 0xb9c4d9fb ^ 0x0ebd4c7f = 0xb7799584 */ bytes4 private constant _INTERFACE_ID_ROYALTIES_RARIBLE = 0xb7799584; /** * @dev Foundation * * bytes4(keccak256('getFees(uint256)')) == 0xd5a06d4c * * => 0xd5a06d4c = 0xd5a06d4c */ bytes4 private constant _INTERFACE_ID_ROYALTIES_FOUNDATION = 0xd5a06d4c; /** * @dev EIP-2981 * * bytes4(keccak256("royaltyInfo(uint256,uint256)")) == 0x2a55205a * * => 0x2a55205a = 0x2a55205a */ bytes4 private constant _INTERFACE_ID_ROYALTIES_EIP2981 = 0x2a55205a; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(ICreatorCore).interfaceId || interfaceId == _CREATOR_CORE_V1 || super.supportsInterface(interfaceId) || interfaceId == _INTERFACE_ID_ROYALTIES_CREATORCORE || interfaceId == _INTERFACE_ID_ROYALTIES_RARIBLE || interfaceId == _INTERFACE_ID_ROYALTIES_FOUNDATION || interfaceId == _INTERFACE_ID_ROYALTIES_EIP2981; } /** * @dev Only allows registered extensions to call the specified function */ function requireExtension() internal view { require(_extensions.contains(msg.sender), "Must be registered extension"); } /** * @dev Only allows non-blacklisted extensions */ function requireNonBlacklist(address extension) internal view { require(!_blacklistedExtensions.contains(extension), "Extension blacklisted"); } /** * @dev See {ICreatorCore-getExtensions}. */ function getExtensions() external view override returns (address[] memory extensions) { extensions = new address[](_extensions.length()); for (uint i; i < _extensions.length();) { extensions[i] = _extensions.at(i); unchecked { ++i; } } return extensions; } /** * @dev Register an extension */ function _registerExtension(address extension, string calldata baseURI, bool baseURIIdentical) internal { require(extension != address(this) && extension.isContract(), "Invalid"); emit ExtensionRegistered(extension, msg.sender); _extensionBaseURI[extension] = baseURI; _extensionBaseURIIdentical[extension] = baseURIIdentical; _extensions.add(extension); _setApproveTransferExtension(extension, true); } /** * @dev See {ICreatorCore-setApproveTransferExtension}. */ function setApproveTransferExtension(bool enabled) external override { requireExtension(); _setApproveTransferExtension(msg.sender, enabled); } /** * @dev Set whether or not tokens minted by the extension defers transfer approvals to the extension */ function _setApproveTransferExtension(address extension, bool enabled) internal virtual; /** * @dev Unregister an extension */ function _unregisterExtension(address extension) internal { emit ExtensionUnregistered(extension, msg.sender); _extensions.remove(extension); } /** * @dev Blacklist an extension */ function _blacklistExtension(address extension) internal { require(extension != address(0) && extension != address(this), "Cannot blacklist yourself"); if (_extensions.contains(extension)) { emit ExtensionUnregistered(extension, msg.sender); _extensions.remove(extension); } if (!_blacklistedExtensions.contains(extension)) { emit ExtensionBlacklisted(extension, msg.sender); _blacklistedExtensions.add(extension); } } /** * @dev Set base token uri for an extension */ function _setBaseTokenURIExtension(string calldata uri, bool identical) internal { _extensionBaseURI[msg.sender] = uri; _extensionBaseURIIdentical[msg.sender] = identical; } /** * @dev Set token uri prefix for an extension */ function _setTokenURIPrefixExtension(string calldata prefix) internal { _extensionURIPrefix[msg.sender] = prefix; } /** * @dev Set token uri for a token of an extension */ function _setTokenURIExtension(uint256 tokenId, string calldata uri) internal { require(_tokensExtension[tokenId] == msg.sender, "Invalid token"); _tokenURIs[tokenId] = uri; } /** * @dev Set base token uri for tokens with no extension */ function _setBaseTokenURI(string memory uri) internal { _extensionBaseURI[address(0)] = uri; } /** * @dev Set token uri prefix for tokens with no extension */ function _setTokenURIPrefix(string calldata prefix) internal { _extensionURIPrefix[address(0)] = prefix; } /** * @dev Set token uri for a token with no extension */ function _setTokenURI(uint256 tokenId, string calldata uri) internal { require(tokenId > 0 && tokenId <= _tokenCount && _tokensExtension[tokenId] == address(0), "Invalid token"); _tokenURIs[tokenId] = uri; } /** * @dev Retrieve a token's URI */ function _tokenURI(uint256 tokenId) internal view returns (string memory) { require(tokenId > 0 && tokenId <= _tokenCount, "Invalid token"); address extension = _tokensExtension[tokenId]; require(!_blacklistedExtensions.contains(extension), "Extension blacklisted"); if (bytes(_tokenURIs[tokenId]).length != 0) { if (bytes(_extensionURIPrefix[extension]).length != 0) { return string(abi.encodePacked(_extensionURIPrefix[extension],_tokenURIs[tokenId])); } return _tokenURIs[tokenId]; } if (ERC165Checker.supportsInterface(extension, type(ICreatorExtensionTokenURI).interfaceId)) { return ICreatorExtensionTokenURI(extension).tokenURI(address(this), tokenId); } if (!_extensionBaseURIIdentical[extension]) { return string(abi.encodePacked(_extensionBaseURI[extension], tokenId.toString())); } else { return _extensionBaseURI[extension]; } } /** * Get token extension */ function _tokenExtension(uint256 tokenId) internal view returns (address extension) { extension = _tokensExtension[tokenId]; require(extension != address(0), "No extension for token"); require(!_blacklistedExtensions.contains(extension), "Extension blacklisted"); return extension; } /** * Helper to get royalties for a token */ function _getRoyalties(uint256 tokenId) view internal returns (address payable[] memory receivers, uint256[] memory bps) { // Get token level royalties RoyaltyConfig[] memory royalties = _tokenRoyalty[tokenId]; if (royalties.length == 0) { // Get extension specific royalties address extension = _tokensExtension[tokenId]; if (extension != address(0)) { if (ERC165Checker.supportsInterface(extension, type(ICreatorExtensionRoyalties).interfaceId)) { (receivers, bps) = ICreatorExtensionRoyalties(extension).getRoyalties(address(this), tokenId); // Extension override exists, just return that if (receivers.length > 0) return (receivers, bps); } royalties = _extensionRoyalty[extension]; } } if (royalties.length == 0) { // Get the default royalty royalties = _extensionRoyalty[address(0)]; } if (royalties.length > 0) { receivers = new address payable[](royalties.length); bps = new uint256[](royalties.length); for (uint i; i < royalties.length;) { receivers[i] = royalties[i].receiver; bps[i] = royalties[i].bps; unchecked { ++i; } } } } /** * Helper to get royalty receivers for a token */ function _getRoyaltyReceivers(uint256 tokenId) view internal returns (address payable[] memory recievers) { (recievers, ) = _getRoyalties(tokenId); } /** * Helper to get royalty basis points for a token */ function _getRoyaltyBPS(uint256 tokenId) view internal returns (uint256[] memory bps) { (, bps) = _getRoyalties(tokenId); } function _getRoyaltyInfo(uint256 tokenId, uint256 value) view internal returns (address receiver, uint256 amount){ (address payable[] memory receivers, uint256[] memory bps) = _getRoyalties(tokenId); require(receivers.length <= 1, "More than 1 royalty receiver"); if (receivers.length == 0) { return (address(this), 0); } return (receivers[0], bps[0]*value/10000); } /** * Set royalties for a token */ function _setRoyalties(uint256 tokenId, address payable[] calldata receivers, uint256[] calldata basisPoints) internal { _checkRoyalties(receivers, basisPoints); delete _tokenRoyalty[tokenId]; _setRoyalties(receivers, basisPoints, _tokenRoyalty[tokenId]); emit RoyaltiesUpdated(tokenId, receivers, basisPoints); } /** * Set royalties for all tokens of an extension */ function _setRoyaltiesExtension(address extension, address payable[] calldata receivers, uint256[] calldata basisPoints) internal { _checkRoyalties(receivers, basisPoints); delete _extensionRoyalty[extension]; _setRoyalties(receivers, basisPoints, _extensionRoyalty[extension]); if (extension == address(0)) { emit DefaultRoyaltiesUpdated(receivers, basisPoints); } else { emit ExtensionRoyaltiesUpdated(extension, receivers, basisPoints); } } /** * Helper function to check that royalties provided are valid */ function _checkRoyalties(address payable[] calldata receivers, uint256[] calldata basisPoints) private pure { require(receivers.length == basisPoints.length, "Invalid input"); uint256 totalBasisPoints; for (uint i; i < basisPoints.length;) { totalBasisPoints += basisPoints[i]; unchecked { ++i; } } require(totalBasisPoints < 10000, "Invalid total royalties"); } /** * Helper function to set royalties */ function _setRoyalties(address payable[] calldata receivers, uint256[] calldata basisPoints, RoyaltyConfig[] storage royalties) private { for (uint i; i < basisPoints.length;) { royalties.push( RoyaltyConfig( { receiver: receivers[i], bps: uint16(basisPoints[i]) } ) ); unchecked { ++i; } } } /** * @dev See {ICreatorCore-getApproveTransfer}. */ function getApproveTransfer() external view override returns (address) { return _approveTransferBase; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "../extensions/ERC721/IERC721CreatorExtensionApproveTransfer.sol"; import "../extensions/ERC721/IERC721CreatorExtensionBurnable.sol"; import "../permissions/ERC721/IERC721CreatorMintPermissions.sol"; import "./IERC721CreatorCore.sol"; import "./CreatorCore.sol"; /** * @dev Core ERC721 creator implementation */ abstract contract ERC721CreatorCore is CreatorCore, IERC721CreatorCore { uint256 constant public VERSION = 2; using EnumerableSet for EnumerableSet.AddressSet; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(CreatorCore, IERC165) returns (bool) { return interfaceId == type(IERC721CreatorCore).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {CreatorCore-_setApproveTransferExtension} */ function _setApproveTransferExtension(address extension, bool enabled) internal override { if (ERC165Checker.supportsInterface(extension, type(IERC721CreatorExtensionApproveTransfer).interfaceId)) { _extensionApproveTransfers[extension] = enabled; emit ExtensionApproveTransferUpdated(extension, enabled); } } /** * @dev Set the base contract's approve transfer contract location */ function _setApproveTransferBase(address extension) internal { _approveTransferBase = extension; emit ApproveTransferUpdated(extension); } /** * @dev Set mint permissions for an extension */ function _setMintPermissions(address extension, address permissions) internal { require(_extensions.contains(extension), "CreatorCore: Invalid extension"); require(permissions == address(0) || ERC165Checker.supportsInterface(permissions, type(IERC721CreatorMintPermissions).interfaceId), "Invalid address"); if (_extensionPermissions[extension] != permissions) { _extensionPermissions[extension] = permissions; emit MintPermissionsUpdated(extension, permissions, msg.sender); } } /** * Check if an extension can mint */ function _checkMintPermissions(address to, uint256 tokenId) internal { if (_extensionPermissions[msg.sender] != address(0)) { IERC721CreatorMintPermissions(_extensionPermissions[msg.sender]).approveMint(msg.sender, to, tokenId); } } /** * Override for post mint actions */ function _postMintBase(address, uint256) internal virtual {} /** * Override for post mint actions */ function _postMintExtension(address, uint256) internal virtual {} /** * Post-burning callback and metadata cleanup */ function _postBurn(address owner, uint256 tokenId) internal virtual { // Callback to originating extension if needed if (_tokensExtension[tokenId] != address(0)) { if (ERC165Checker.supportsInterface(_tokensExtension[tokenId], type(IERC721CreatorExtensionBurnable).interfaceId)) { IERC721CreatorExtensionBurnable(_tokensExtension[tokenId]).onBurn(owner, tokenId); } } // Clear metadata (if any) if (bytes(_tokenURIs[tokenId]).length != 0) { delete _tokenURIs[tokenId]; } // Delete token origin extension tracking delete _tokensExtension[tokenId]; } /** * Approve a transfer */ function _approveTransfer(address from, address to, uint256 tokenId) internal { if (_extensionApproveTransfers[_tokensExtension[tokenId]]) { require(IERC721CreatorExtensionApproveTransfer(_tokensExtension[tokenId]).approveTransfer(msg.sender, from, to, tokenId), "Extension approval failure"); } else if (_approveTransferBase != address(0)) { require(IERC721CreatorExtensionApproveTransfer(_approveTransferBase).approveTransfer(msg.sender, from, to, tokenId), "Extension approval failure"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @dev Core creator interface */ interface ICreatorCore is IERC165 { event ExtensionRegistered(address indexed extension, address indexed sender); event ExtensionUnregistered(address indexed extension, address indexed sender); event ExtensionBlacklisted(address indexed extension, address indexed sender); event MintPermissionsUpdated(address indexed extension, address indexed permissions, address indexed sender); event RoyaltiesUpdated(uint256 indexed tokenId, address payable[] receivers, uint256[] basisPoints); event DefaultRoyaltiesUpdated(address payable[] receivers, uint256[] basisPoints); event ApproveTransferUpdated(address extension); event ExtensionRoyaltiesUpdated(address indexed extension, address payable[] receivers, uint256[] basisPoints); event ExtensionApproveTransferUpdated(address indexed extension, bool enabled); /** * @dev gets address of all extensions */ function getExtensions() external view returns (address[] memory); /** * @dev add an extension. Can only be called by contract owner or admin. * extension address must point to a contract implementing ICreatorExtension. * Returns True if newly added, False if already added. */ function registerExtension(address extension, string calldata baseURI) external; /** * @dev add an extension. Can only be called by contract owner or admin. * extension address must point to a contract implementing ICreatorExtension. * Returns True if newly added, False if already added. */ function registerExtension(address extension, string calldata baseURI, bool baseURIIdentical) external; /** * @dev add an extension. Can only be called by contract owner or admin. * Returns True if removed, False if already removed. */ function unregisterExtension(address extension) external; /** * @dev blacklist an extension. Can only be called by contract owner or admin. * This function will destroy all ability to reference the metadata of any tokens created * by the specified extension. It will also unregister the extension if needed. * Returns True if removed, False if already removed. */ function blacklistExtension(address extension) external; /** * @dev set the baseTokenURI of an extension. Can only be called by extension. */ function setBaseTokenURIExtension(string calldata uri) external; /** * @dev set the baseTokenURI of an extension. Can only be called by extension. * For tokens with no uri configured, tokenURI will return "uri+tokenId" */ function setBaseTokenURIExtension(string calldata uri, bool identical) external; /** * @dev set the common prefix of an extension. Can only be called by extension. * If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI" * Useful if you want to use ipfs/arweave */ function setTokenURIPrefixExtension(string calldata prefix) external; /** * @dev set the tokenURI of a token extension. Can only be called by extension that minted token. */ function setTokenURIExtension(uint256 tokenId, string calldata uri) external; /** * @dev set the tokenURI of a token extension for multiple tokens. Can only be called by extension that minted token. */ function setTokenURIExtension(uint256[] memory tokenId, string[] calldata uri) external; /** * @dev set the baseTokenURI for tokens with no extension. Can only be called by owner/admin. * For tokens with no uri configured, tokenURI will return "uri+tokenId" */ function setBaseTokenURI(string calldata uri) external; /** * @dev set the common prefix for tokens with no extension. Can only be called by owner/admin. * If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI" * Useful if you want to use ipfs/arweave */ function setTokenURIPrefix(string calldata prefix) external; /** * @dev set the tokenURI of a token with no extension. Can only be called by owner/admin. */ function setTokenURI(uint256 tokenId, string calldata uri) external; /** * @dev set the tokenURI of multiple tokens with no extension. Can only be called by owner/admin. */ function setTokenURI(uint256[] memory tokenIds, string[] calldata uris) external; /** * @dev set a permissions contract for an extension. Used to control minting. */ function setMintPermissions(address extension, address permissions) external; /** * @dev Configure so transfers of tokens created by the caller (must be extension) gets approval * from the extension before transferring */ function setApproveTransferExtension(bool enabled) external; /** * @dev get the extension of a given token */ function tokenExtension(uint256 tokenId) external view returns (address); /** * @dev Set default royalties */ function setRoyalties(address payable[] calldata receivers, uint256[] calldata basisPoints) external; /** * @dev Set royalties of a token */ function setRoyalties(uint256 tokenId, address payable[] calldata receivers, uint256[] calldata basisPoints) external; /** * @dev Set royalties of an extension */ function setRoyaltiesExtension(address extension, address payable[] calldata receivers, uint256[] calldata basisPoints) external; /** * @dev Get royalites of a token. Returns list of receivers and basisPoints */ function getRoyalties(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory); // Royalty support for various other standards function getFeeRecipients(uint256 tokenId) external view returns (address payable[] memory); function getFeeBps(uint256 tokenId) external view returns (uint[] memory); function getFees(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory); function royaltyInfo(uint256 tokenId, uint256 value) external view returns (address, uint256); /** * @dev Set the default approve transfer contract location. */ function setApproveTransfer(address extension) external; /** * @dev Get the default approve transfer contract location. */ function getApproveTransfer() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "./ICreatorCore.sol"; /** * @dev Core ERC721 creator interface */ interface IERC721CreatorCore is ICreatorCore { /** * @dev mint a token with no extension. Can only be called by an admin. * Returns tokenId minted */ function mintBase(address to) external returns (uint256); /** * @dev mint a token with no extension. Can only be called by an admin. * Returns tokenId minted */ function mintBase(address to, string calldata uri) external returns (uint256); /** * @dev batch mint a token with no extension. Can only be called by an admin. * Returns tokenId minted */ function mintBaseBatch(address to, uint16 count) external returns (uint256[] memory); /** * @dev batch mint a token with no extension. Can only be called by an admin. * Returns tokenId minted */ function mintBaseBatch(address to, string[] calldata uris) external returns (uint256[] memory); /** * @dev mint a token. Can only be called by a registered extension. * Returns tokenId minted */ function mintExtension(address to) external returns (uint256); /** * @dev mint a token. Can only be called by a registered extension. * Returns tokenId minted */ function mintExtension(address to, string calldata uri) external returns (uint256); /** * @dev batch mint a token. Can only be called by a registered extension. * Returns tokenIds minted */ function mintExtensionBatch(address to, uint16 count) external returns (uint256[] memory); /** * @dev batch mint a token. Can only be called by a registered extension. * Returns tokenId minted */ function mintExtensionBatch(address to, string[] calldata uris) external returns (uint256[] memory); /** * @dev burn a token. Can only be called by token owner or approved address. * On burn, calls back to the registered extension's onBurn method */ function burn(uint256 tokenId) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@manifoldxyz/libraries-solidity/contracts/access/AdminControl.sol"; import "./core/ERC721CreatorCore.sol"; /** * @dev ERC721Creator implementation */ contract ERC721Creator is AdminControl, ERC721, ERC721CreatorCore { constructor (string memory _name, string memory _symbol) ERC721(_name, _symbol) { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC721CreatorCore, AdminControl) returns (bool) { return ERC721CreatorCore.supportsInterface(interfaceId) || ERC721.supportsInterface(interfaceId) || AdminControl.supportsInterface(interfaceId); } function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override { _approveTransfer(from, to, tokenId); } /** * @dev See {ICreatorCore-registerExtension}. */ function registerExtension(address extension, string calldata baseURI) external override adminRequired { requireNonBlacklist(extension); _registerExtension(extension, baseURI, false); } /** * @dev See {ICreatorCore-registerExtension}. */ function registerExtension(address extension, string calldata baseURI, bool baseURIIdentical) external override adminRequired { requireNonBlacklist(extension); _registerExtension(extension, baseURI, baseURIIdentical); } /** * @dev See {ICreatorCore-unregisterExtension}. */ function unregisterExtension(address extension) external override adminRequired { _unregisterExtension(extension); } /** * @dev See {ICreatorCore-blacklistExtension}. */ function blacklistExtension(address extension) external override adminRequired { _blacklistExtension(extension); } /** * @dev See {ICreatorCore-setBaseTokenURIExtension}. */ function setBaseTokenURIExtension(string calldata uri) external override { requireExtension(); _setBaseTokenURIExtension(uri, false); } /** * @dev See {ICreatorCore-setBaseTokenURIExtension}. */ function setBaseTokenURIExtension(string calldata uri, bool identical) external override { requireExtension(); _setBaseTokenURIExtension(uri, identical); } /** * @dev See {ICreatorCore-setTokenURIPrefixExtension}. */ function setTokenURIPrefixExtension(string calldata prefix) external override { requireExtension(); _setTokenURIPrefixExtension(prefix); } /** * @dev See {ICreatorCore-setTokenURIExtension}. */ function setTokenURIExtension(uint256 tokenId, string calldata uri) external override { requireExtension(); _setTokenURIExtension(tokenId, uri); } /** * @dev See {ICreatorCore-setTokenURIExtension}. */ function setTokenURIExtension(uint256[] memory tokenIds, string[] calldata uris) external override { requireExtension(); require(tokenIds.length == uris.length, "Invalid input"); for (uint i; i < tokenIds.length;) { _setTokenURIExtension(tokenIds[i], uris[i]); unchecked { ++i; } } } /** * @dev See {ICreatorCore-setBaseTokenURI}. */ function setBaseTokenURI(string calldata uri) external override adminRequired { _setBaseTokenURI(uri); } /** * @dev See {ICreatorCore-setTokenURIPrefix}. */ function setTokenURIPrefix(string calldata prefix) external override adminRequired { _setTokenURIPrefix(prefix); } /** * @dev See {ICreatorCore-setTokenURI}. */ function setTokenURI(uint256 tokenId, string calldata uri) external override adminRequired { _setTokenURI(tokenId, uri); } /** * @dev See {ICreatorCore-setTokenURI}. */ function setTokenURI(uint256[] memory tokenIds, string[] calldata uris) external override adminRequired { require(tokenIds.length == uris.length, "Invalid input"); for (uint i; i < tokenIds.length;) { _setTokenURI(tokenIds[i], uris[i]); unchecked { ++i; } } } /** * @dev See {ICreatorCore-setMintPermissions}. */ function setMintPermissions(address extension, address permissions) external override adminRequired { _setMintPermissions(extension, permissions); } /** * @dev See {IERC721CreatorCore-mintBase}. */ function mintBase(address to) public virtual override nonReentrant adminRequired returns(uint256) { return _mintBase(to, ""); } /** * @dev See {IERC721CreatorCore-mintBase}. */ function mintBase(address to, string calldata uri) public virtual override nonReentrant adminRequired returns(uint256) { return _mintBase(to, uri); } /** * @dev See {IERC721CreatorCore-mintBaseBatch}. */ function mintBaseBatch(address to, uint16 count) public virtual override nonReentrant adminRequired returns(uint256[] memory tokenIds) { tokenIds = new uint256[](count); for (uint16 i = 0; i < count;) { tokenIds[i] = _mintBase(to, ""); unchecked { ++i; } } } /** * @dev See {IERC721CreatorCore-mintBaseBatch}. */ function mintBaseBatch(address to, string[] calldata uris) public virtual override nonReentrant adminRequired returns(uint256[] memory tokenIds) { tokenIds = new uint256[](uris.length); for (uint i; i < uris.length;) { tokenIds[i] = _mintBase(to, uris[i]); unchecked { ++i; } } } /** * @dev Mint token with no extension */ function _mintBase(address to, string memory uri) internal virtual returns(uint256 tokenId) { ++_tokenCount; tokenId = _tokenCount; _safeMint(to, tokenId); if (bytes(uri).length > 0) { _tokenURIs[tokenId] = uri; } // Call post mint _postMintBase(to, tokenId); } /** * @dev See {IERC721CreatorCore-mintExtension}. */ function mintExtension(address to) public virtual override nonReentrant returns(uint256) { requireExtension(); return _mintExtension(to, ""); } /** * @dev See {IERC721CreatorCore-mintExtension}. */ function mintExtension(address to, string calldata uri) public virtual override nonReentrant returns(uint256) { requireExtension(); return _mintExtension(to, uri); } /** * @dev See {IERC721CreatorCore-mintExtensionBatch}. */ function mintExtensionBatch(address to, uint16 count) public virtual override nonReentrant returns(uint256[] memory tokenIds) { requireExtension(); tokenIds = new uint256[](count); for (uint16 i = 0; i < count;) { tokenIds[i] = _mintExtension(to, ""); unchecked { ++i; } } } /** * @dev See {IERC721CreatorCore-mintExtensionBatch}. */ function mintExtensionBatch(address to, string[] calldata uris) public virtual override nonReentrant returns(uint256[] memory tokenIds) { requireExtension(); tokenIds = new uint256[](uris.length); for (uint i; i < uris.length;) { tokenIds[i] = _mintExtension(to, uris[i]); unchecked { ++i; } } } /** * @dev Mint token via extension */ function _mintExtension(address to, string memory uri) internal virtual returns(uint256 tokenId) { ++_tokenCount; tokenId = _tokenCount; _checkMintPermissions(to, tokenId); // Track the extension that minted the token _tokensExtension[tokenId] = msg.sender; _safeMint(to, tokenId); if (bytes(uri).length > 0) { _tokenURIs[tokenId] = uri; } // Call post mint _postMintExtension(to, tokenId); } /** * @dev See {IERC721CreatorCore-tokenExtension}. */ function tokenExtension(uint256 tokenId) public view virtual override returns (address) { require(_exists(tokenId), "Nonexistent token"); return _tokenExtension(tokenId); } /** * @dev See {IERC721CreatorCore-burn}. */ function burn(uint256 tokenId) public virtual override nonReentrant { require(_isApprovedOrOwner(msg.sender, tokenId), "Caller is not owner nor approved"); address owner = ownerOf(tokenId); _burn(tokenId); _postBurn(owner, tokenId); } /** * @dev See {ICreatorCore-setRoyalties}. */ function setRoyalties(address payable[] calldata receivers, uint256[] calldata basisPoints) external override adminRequired { _setRoyaltiesExtension(address(0), receivers, basisPoints); } /** * @dev See {ICreatorCore-setRoyalties}. */ function setRoyalties(uint256 tokenId, address payable[] calldata receivers, uint256[] calldata basisPoints) external override adminRequired { require(_exists(tokenId), "Nonexistent token"); _setRoyalties(tokenId, receivers, basisPoints); } /** * @dev See {ICreatorCore-setRoyaltiesExtension}. */ function setRoyaltiesExtension(address extension, address payable[] calldata receivers, uint256[] calldata basisPoints) external override adminRequired { _setRoyaltiesExtension(extension, receivers, basisPoints); } /** * @dev See {ICreatorCore-getRoyalties}. */ function getRoyalties(uint256 tokenId) external view virtual override returns (address payable[] memory, uint256[] memory) { require(_exists(tokenId), "Nonexistent token"); return _getRoyalties(tokenId); } /** * @dev See {ICreatorCore-getFees}. */ function getFees(uint256 tokenId) external view virtual override returns (address payable[] memory, uint256[] memory) { require(_exists(tokenId), "Nonexistent token"); return _getRoyalties(tokenId); } /** * @dev See {ICreatorCore-getFeeRecipients}. */ function getFeeRecipients(uint256 tokenId) external view virtual override returns (address payable[] memory) { require(_exists(tokenId), "Nonexistent token"); return _getRoyaltyReceivers(tokenId); } /** * @dev See {ICreatorCore-getFeeBps}. */ function getFeeBps(uint256 tokenId) external view virtual override returns (uint[] memory) { require(_exists(tokenId), "Nonexistent token"); return _getRoyaltyBPS(tokenId); } /** * @dev See {ICreatorCore-royaltyInfo}. */ function royaltyInfo(uint256 tokenId, uint256 value) external view virtual override returns (address, uint256) { require(_exists(tokenId), "Nonexistent token"); return _getRoyaltyInfo(tokenId, value); } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { require(_exists(tokenId), "Nonexistent token"); return _tokenURI(tokenId); } /** * @dev See {ICreatorCore-setApproveTransfer}. */ function setApproveTransfer(address extension) external override adminRequired { _setApproveTransferBase(extension); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * Implement this if you want your extension to approve a transfer */ interface IERC721CreatorExtensionApproveTransfer is IERC165 { /** * @dev Set whether or not the creator will check the extension for approval of token transfer */ function setApproveTransfer(address creator, bool enabled) external; /** * @dev Called by creator contract to approve a transfer */ function approveTransfer(address operator, address from, address to, uint256 tokenId) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @dev Your extension is required to implement this interface if it wishes * to receive the onBurn callback whenever a token the extension created is * burned */ interface IERC721CreatorExtensionBurnable is IERC165 { /** * @dev callback handler for burn events */ function onBurn(address owner, uint256 tokenId) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @dev Implement this if you want your extension to have overloadable royalties */ interface ICreatorExtensionRoyalties is IERC165 { /** * Get the royalties for a given creator/tokenId */ function getRoyalties(address creator, uint256 tokenId) external view returns (address payable[] memory, uint256[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @dev Implement this if you want your extension to have overloadable URI's */ interface ICreatorExtensionTokenURI is IERC165 { /** * Get the uri for a given creator/tokenId */ function tokenURI(address creator, uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721Creator compliant extension contracts. */ interface IERC721CreatorMintPermissions is IERC165 { /** * @dev get approval to mint */ function approveMint(address extension, address to, uint256 tokenId) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "./IAdminControl.sol"; abstract contract AdminControl is Ownable, IAdminControl, ERC165 { using EnumerableSet for EnumerableSet.AddressSet; // Track registered admins EnumerableSet.AddressSet private _admins; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IAdminControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Only allows approved admins to call the specified function */ modifier adminRequired() { require(owner() == msg.sender || _admins.contains(msg.sender), "AdminControl: Must be owner or admin"); _; } /** * @dev See {IAdminControl-getAdmins}. */ function getAdmins() external view override returns (address[] memory admins) { admins = new address[](_admins.length()); for (uint i = 0; i < _admins.length(); i++) { admins[i] = _admins.at(i); } return admins; } /** * @dev See {IAdminControl-approveAdmin}. */ function approveAdmin(address admin) external override onlyOwner { if (!_admins.contains(admin)) { emit AdminApproved(admin, msg.sender); _admins.add(admin); } } /** * @dev See {IAdminControl-revokeAdmin}. */ function revokeAdmin(address admin) external override onlyOwner { if (_admins.contains(admin)) { emit AdminRevoked(admin, msg.sender); _admins.remove(admin); } } /** * @dev See {IAdminControl-isAdmin}. */ function isAdmin(address admin) public override view returns (bool) { return (owner() == admin || _admins.contains(admin)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @dev Interface for admin control */ interface IAdminControl is IERC165 { event AdminApproved(address indexed account, address indexed sender); event AdminRevoked(address indexed account, address indexed sender); /** * @dev gets address of all admins */ function getAdmins() external view returns (address[] memory); /** * @dev add an admin. Can only be called by contract owner. */ function approveAdmin(address admin) external; /** * @dev remove an admin. Can only be called by contract owner. */ function revokeAdmin(address admin) external; /** * @dev checks whether or not given address is an admin * Returns True if they are */ function isAdmin(address admin) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @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) (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 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.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 = _owners[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 nor 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 nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _owners[tokenId] != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { 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); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } /** * @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. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/extensions/ERC721URIStorage.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; /** * @dev ERC721 token with storage based token URI management. */ abstract contract ERC721URIStorage is ERC721 { using Strings for uint256; // Optional mapping for token URIs mapping(uint256 => string) private _tokenURIs; /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory _tokenURI = _tokenURIs[tokenId]; string memory base = _baseURI(); // If there is no base URI, return the token URI. if (bytes(base).length == 0) { return _tokenURI; } // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked). if (bytes(_tokenURI).length > 0) { return string(abi.encodePacked(base, _tokenURI)); } return super.tokenURI(tokenId); } /** * @dev Sets `_tokenURI` as the tokenURI of `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual { require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token"); _tokenURIs[tokenId] = _tokenURI; } /** * @dev See {ERC721-_burn}. This override additionally checks to see if a * token-specific URI was set for the token, and if so, it deletes the token URI from * the storage mapping. */ function _burn(uint256 tokenId) internal virtual override { super._burn(tokenId); if (bytes(_tokenURIs[tokenId]).length != 0) { delete _tokenURIs[tokenId]; } } }
// 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.7.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: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (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.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library Counters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } }
// 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 (last updated v4.7.2) (utils/introspection/ERC165Checker.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Library used to query support of an interface declared via {IERC165}. * * Note that these functions return the actual result of the query: they do not * `revert` if an interface is not supported. It is up to the caller to decide * what to do in these cases. */ library ERC165Checker { // As per the EIP-165 spec, no interface should ever match 0xffffffff bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; /** * @dev Returns true if `account` supports the {IERC165} interface, */ function supportsERC165(address account) internal view returns (bool) { // Any contract that implements ERC165 must explicitly indicate support of // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid return _supportsERC165Interface(account, type(IERC165).interfaceId) && !_supportsERC165Interface(account, _INTERFACE_ID_INVALID); } /** * @dev Returns true if `account` supports the interface defined by * `interfaceId`. Support for {IERC165} itself is queried automatically. * * See {IERC165-supportsInterface}. */ function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { // query support of both ERC165 as per the spec and support of _interfaceId return supportsERC165(account) && _supportsERC165Interface(account, interfaceId); } /** * @dev Returns a boolean array where each value corresponds to the * interfaces passed in and whether they're supported or not. This allows * you to batch check interfaces for a contract where your expectation * is that some interfaces may not be supported. * * See {IERC165-supportsInterface}. * * _Available since v3.4._ */ function getSupportedInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool[] memory) { // an array of booleans corresponding to interfaceIds and whether they're supported or not bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length); // query support of ERC165 itself if (supportsERC165(account)) { // query support of each interface in interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]); } } return interfaceIdsSupported; } /** * @dev Returns true if `account` supports all the interfaces defined in * `interfaceIds`. Support for {IERC165} itself is queried automatically. * * Batch-querying can lead to gas savings by skipping repeated checks for * {IERC165} support. * * See {IERC165-supportsInterface}. */ function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { // query support of ERC165 itself if (!supportsERC165(account)) { return false; } // query support of each interface in _interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { if (!_supportsERC165Interface(account, interfaceIds[i])) { return false; } } // all interfaces supported return true; } /** * @notice Query if a contract implements an interface, does not check ERC165 support * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return true if the contract at account indicates support of the interface with * identifier interfaceId, false otherwise * @dev Assumes that account contains a contract that supports ERC165, otherwise * the behavior of this method is undefined. This precondition can be checked * with {supportsERC165}. * Interface identification is specified in ERC-165. */ function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) { // prepare call bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId); // perform static call bool success; uint256 returnSize; uint256 returnValue; assembly { success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20) returnSize := returndatasize() returnValue := mload(0x00) } return success && returnSize >= 0x20 && returnValue > 0; } }
// 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.7.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. It 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)`. // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`. // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`. // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a // good first aproximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1; uint256 x = a; if (x >> 128 > 0) { x >>= 128; result <<= 64; } if (x >> 64 > 0) { x >>= 64; result <<= 32; } if (x >> 32 > 0) { x >>= 32; result <<= 16; } if (x >> 16 > 0) { x >>= 16; result <<= 8; } if (x >> 8 > 0) { x >>= 8; result <<= 4; } if (x >> 4 > 0) { x >>= 4; result <<= 2; } if (x >> 2 > 0) { result <<= 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) { uint256 result = sqrt(a); if (rounding == Rounding.Up && result * result < a) { result += 1; } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_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) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; library Figure0DigitLib { function S1() public pure returns (string memory) { return "000000000000000000000000000000000000000001111111100000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000011111111001111111100000000000000000000000000000000111111100011111110000000000000000000000000000000000111111100011111110000000000000000000000000000000011111100001111110000000000000000000000000000000000011111100001111110000000000000000000000000000000000011111100001111110000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000011100000001110000000000000000000000000000000000000011100000001110000000000000000000000000000000000000011100000001110000000000000000000000000000000000000011100000001110000000000000000000000000000000000000011100000001110000000000000000000000000000000000000011100000001110000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000111111110011111111001111111100000000000000000000001111111000111111100011111110000000000000000000000001111111000111111100011111110000000000000000000000111111000011111100001111110000000000000000000000000111111000011111100001111110000000000000000000000000111111000011111100001111110000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000111000000011100000001110000000000000000000000000000111000000011100000001110000000000000000000000000000111000000011100000001110000000000000000000000000000111000000011100000001110000000000000000000000000000111000000011100000001110000000000000000000000000000111000000011100000001110000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000001111111100111111110011111111001111111100000000000011111110001111111000111111100011111110000000000000011111110001111111000111111100011111110000000000001111110000111111000011111100001111110000000000000001111110000111111000011111100001111110000000000000001111110000111111000011111100001111110000000000001111100000111110000011111000001111100000000000000001111100000111110000011111000001111100000000000000001111100000111110000011111000001111100000000000000001111100000111110000011111000001111100000000000011110000001111000000111100000011110000000000000000011110000001111000000111100000011110000000000000000011110000001111000000111100000011110000000000000000011110000001111000000111100000011110000000000000000011110000001111000000111100000011110000000000001110000000111000000011100000001110000000000000000001110000000111000000011100000001110000000000000000001110000000111000000011100000001110000000000000000001110000000111000000011100000001110000000000000000001110000000111000000011100000001110000000000000000001110000000111000000011100000001110000000000001100000000110000000011000000001100000000000000000001100000000110000000011000000001100000000000000000001100000000110000000011000000001100000000000000000001100000000110000000011000000001100000000000000000001100000000110000000011000000001100000000000000000001100000000110000000011000000001100000000000000000001100000000110000000011000000001100000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010"; } function S2() public pure returns (string memory) { return "010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000000000000010000000001000000000100000000010000000000001100000000110000000011000000001100000000000000000001100000000110000000011000000001100000000000000000001100000000110000000011000000001100000000000000000001100000000110000000011000000001100000000000000000001100000000110000000011000000001100000000000000000001100000000110000000011000000001100000000000000000001100000000110000000011000000001100000000000011100000001110000000111000000011100000000000000000011100000001110000000111000000011100000000000000000011100000001110000000111000000011100000000000000000011100000001110000000111000000011100000000000000000011100000001110000000111000000011100000000000000000011100000001110000000111000000011100000000000011110000001111000000111100000011110000000000000000011110000001111000000111100000011110000000000000000011110000001111000000111100000011110000000000000000011110000001111000000111100000011110000000000000000011110000001111000000111100000011110000000000001111100000111110000011111000001111100000000000000001111100000111110000011111000001111100000000000000001111100000111110000011111000001111100000000000000001111100000111110000011111000001111100000000000011111100001111110000111111000011111100000000000000011111100001111110000111111000011111100000000000000011111100001111110000111111000011111100000000000011111110001111111000111111100011111110000000000000011111110001111111000111111100011111110000000000001111111100111111110011111111001111111100000000000010000000001000000000100000000000000000000000000000010000000001000000000100000000000000000000000000000010000000001000000000100000000000000000000000000000010000000001000000000100000000000000000000000000000010000000001000000000100000000000000000000000000000010000000001000000000100000000000000000000000000000010000000001000000000100000000000000000000000000000010000000001000000000100000000000000000000001100000000110000000011000000000000000000000000000001100000000110000000011000000000000000000000000000001100000000110000000011000000000000000000000000000001100000000110000000011000000000000000000000000000001100000000110000000011000000000000000000000000000001100000000110000000011000000000000000000000000000001100000000110000000011000000000000000000000011100000001110000000111000000000000000000000000000011100000001110000000111000000000000000000000000000011100000001110000000111000000000000000000000000000011100000001110000000111000000000000000000000000000011100000001110000000111000000000000000000000000000011100000001110000000111000000000000000000000011110000001111000000111100000000000000000000000000011110000001111000000111100000000000000000000000000011110000001111000000111100000000000000000000000000011110000001111000000111100000000000000000000000000011110000001111000000111100000000000000000000001111100000111110000011111000000000000000000000000001111100000111110000011111000000000000000000000000001111100000111110000011111000000000000000000000000001111100000111110000011111000000000000000000000011111100001111110000111111000000000000000000000000011111100001111110000111111000000000000000000000000011111100001111110000111111000000000000000000000011111110001111111000111111100000000000000000000000011111110001111111000111111100000000000000000000001111111100111111110011111111000000000000000000000010000000001000000000000000000000000000000000000000010000000001000000000000000000000000000000000000000010000000001000000000000000000000000000000000000000010000000001000000000000000000000000000000000000000010000000001000000000000000000000000000000000000000010000000001000000000000000000000000000000000000000010000000001000000000000000000000000000000000000000010000000001000000000000000000000000000000001100000000110000000000000000000000000000000000000001100000000110000000000000000000000000000000000000001100000000110000000000000000000000000000000000000001100000000110000000000000000000000000000000000000001100000000110000000000000000000000000000000000000001100000000110000000000000000000000000000000000000001100000000110000000000000000000000000000000011100000001110000000000000000000000000000000000000011100000001110000000000000000000000000000000000000011100000001110000000000000000000000000000000000000011100000001110000000000000000000000000000000000000011100000001110000000000000000000000000000000000000011100000001110000000000000000000000000000000011110000001111000000000000000000000000000000000000011110000001111000000000000000000000000000000000000011110000001111000000000000000000000000000000000000011110000001111000000000000000000000000000000000000011110000001111000000000000000000000000000000001111100000111110000000000000000000000000000000000001111100000111110000000000000000000000000000000000001111100000111110000000000000000000000000000000000001111100000111110000000000000000000000000000000011111100001111110000000000000000000000000000000000011111100001111110000000000000000000000000000000000011111100001111110000000000000000000000000000000011111110001111111000000000000000000000000000000000011111110001111111000000000000000000000000000000001111111100111111110000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000001111111100000000000000000000000000000000000000000"; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; library Figure1DigitLib { function S1() public pure returns (string memory) { return "00000000011000000001100000000110000000011000000001000000000100000000011000000001100000000110000000010000000001000000000100000000011000000001100000000100000000010000000001000000000100000000011000000001000000000111000000011100000001110000000111000000010000000001000000000111000000011100000001110000000100000000010000000001000000000111000000011100000001000000000100000000010000000001000000000111000000010000000001111000000111100000011110000001111000000100000000010000000001111000000111100000011110000001000000000100000000010000000001111000000111100000010000000001000000000100000000010000000001111000000100000000111110000011111000001111100000111110000011000000001100000000111110000011111000001111100000110000000011000000001100000000111110000011111000001100000000110000000011000000001100000000111110000011000000011111100001111110000111111000011111100001110000000111000000011111100001111110000111111000011100000001110000000111000000011111100001111110000111000000011100000001110000000111000000011111100001110000000011110000001111000000111100000011110000001100000000110000000011110000001111000000111100000011000000001100000000110000000011110000001111000000110000000011000000001100000000110000000011110000001100000000111000000011100000001110000000111000000011000000001100000000111000000011100000001110000000110000000011000000001100000000111000000011100000001100000000110000000011000000001100000000111000000011"; } function S2() public pure returns (string memory) { return "10000000011000000001100000000110000000010000000000100000000110000000011000000001000000000000000000001000000001100000000100000000000000000000000000000010000000010000000000000000000000000000000000000000110000000111000000011100000001110000000100000000001100000001110000000111000000010000000000000000000011000000011100000001000000000000000000000000000000110000000100000000000000000000000000000000000000001110000001111000000111100000011110000001000000000011100000011110000001111000000100000000000000000000111000000111100000010000000000000000000000000000001110000001000000000000000000000000000000000000000011100000111110000011111000001111100000110000000000111000001111100000111110000011000000000000000000001110000011111000001100000000000000000000000000000011100000110000000000000000000000000000000000000000111000011111100001111110000111111000011100000000001110000111111000011111100001110000000000000000000011100001111110000111000000000000000000000000000000111000011100000000000000000000000000000000000000001100000011110000001111000000111100000011000000000011000000111100000011110000001100000000000000000000110000001111000000110000000000000000000000000000001100000011000000000000000000000000000000000000000010000000111000000011100000001110000000110000000000100000001110000000111000000011000000000000000000001000000011100000001100000000000000000000000000000010000000110000000000000000000000000000000000000000"; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; library Figure2DigitLib { function S1() public pure returns (string memory) { return "000000000011111111101111111110111111111000000000000000000000111111110011111111001111111100000000000000000000001111111000111111100011111110000000000000000000000011111100001111110000111111000000000000000000000000111110000011111000001111100000000000000000000000001111000000111100000011110000000000000000000000000011100000001110000000111000000000000000000000000000110000000011000000001100000000000000000000000000001000000000100000000010000000000000000000000000000011111111101111111110000000000000000000000000000000111111110011111111000000000000000000000000000000001111111000111111100000000000000000000000000000000011111100001111110000000000000000000000000000000000111110000011111000000000000000000000000000000000001111000000111100000000000000000000000000000000000011100000001110000000000000000000000000000000000000110000000011000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000001111111110111111111000000000000000000000000000000011111111001111111100000000000000000000000000000000111111100011111110000000000000000000000000000000001111110000111111000000000000000000000000000000000011111000001111100000000000000000000000000000000000111100000011110000000000000000000000000000000000001110000000111000000000000000000000000000000000000011000000001100000000000000000000000000000000000000100000000010000000000000000000000000000011111111100000000000000000000000000000000000000000111111110000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001111111110000000000000000000000000000000000000000011111111000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000111111111000000000000000000000000000000000000000001111111100000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000010000000000000000000"; } function S2() public pure returns (string memory) { return "000000000000000000010000000001000000000100000000000000000000000000001100000000110000000011000000000000000000000000000111000000011100000001110000000000000000000000000011110000001111000000111100000000000000000000000001111100000111110000011111000000000000000000000000111111000011111100001111110000000000000000000000011111110001111111000111111100000000000000000000001111111100111111110011111111000000000000000000000111111111011111111101111111110000000000000000000000000000010000000001000000000000000000000000000000000000001100000000110000000000000000000000000000000000000111000000011100000000000000000000000000000000000011110000001111000000000000000000000000000000000001111100000111110000000000000000000000000000000000111111000011111100000000000000000000000000000000011111110001111111000000000000000000000000000000001111111100111111110000000000000000000000000000000111111111011111111100000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000110000000011000000000000000000000000000000000000011100000001110000000000000000000000000000000000001111000000111100000000000000000000000000000000000111110000011111000000000000000000000000000000000011111100001111110000000000000000000000000000000001111111000111111100000000000000000000000000000000111111110011111111000000000000000000000000000000011111111101111111110000000000000000000000000000010000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000001111111100000000000000000000000000000000000000000111111111000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000111111110000000000000000000000000000000000000000011111111100000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000011111111000000000000000000000000000000000000000001111111110000000000"; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; library Figure3DigitLib { function S1() public pure returns (string memory) { return "000000000011111111101111111110111111111000000000000000000000111111110011111111001111111100000000000000000000001111111000111111100011111110000000000000000000000011111100001111110000111111000000000000000000000000111110000011111000001111100000000000000000000000001111000000111100000011110000000000000000000000000011100000001110000000111000000000000000000000000000110000000011000000001100000000000000000000000000001000000000100000000010000000000000000000000000000011111111101111111110000000000000000000000000000000111111110011111111000000000000000000000000000000001111111000111111100000000000000000000000000000000011111100001111110000000000000000000000000000000000111110000011111000000000000000000000000000000000001111000000111100000000000000000000000000000000000011100000001110000000000000000000000000000000000000110000000011000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000001111111110111111111000000000000000000000000000000011111111001111111100000000000000000000000000000000111111100011111110000000000000000000000000000000001111110000111111000000000000000000000000000000000011111000001111100000000000000000000000000000000000111100000011110000000000000000000000000000000000001110000000111000000000000000000000000000000000000011000000001100000000000000000000000000000000000000100000000010000000000000000000000000000011111111100000000000000000000000000000000000000000111111110000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001111111110000000000000000000000000000000000000000011111111000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000111111111000000000000000000000000000000000000000001111111100000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000010000000000000000000"; } function S2() public pure returns (string memory) { return S1(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; library Figure4DigitLib { function S1() public pure returns (string memory) { return "011111110101111111010111111101011111110100000000000111111101011111110101111111010000000000000000000001111111010111111101000000000000000000000000000000011111101101111110110111111011011111101100000000000111111011011111101101111110110000000000000000000001111110110111111011000000000000000000000000000000011111011101111101110111110111011111011100000000000111110111011111011101111101110000000000000000000001111101110111110111000000000000000000000000000000011110111101111011110111101111011110111100000000000111101111011110111101111011110000000000000000000001111011110111101111000000000000000000000000000000001111110100111111010011111101001111110100000000000011111101001111110100111111010000000000000000000000111111010011111101000000000000000000000000000000001111101100111110110011111011001111101100000000000011111011001111101100111110110000000000000000000000111110110011111011000000000000000000000000000000001111011100111101110011110111001111011100000000000011110111001111011100111101110000000000000000000000111101110011110111000000000000000000000000000000001110111100111011110011101111001110111100000000000011101111001110111100111011110000000000000000000000111011110011101111000000000000000000000000000000000111110100011111010001111101000111110100000000000001111101000111110100011111010000000000000000000000011111010001111101000000000000000000000000000000000111101100011110110001111011000111101100000000000001111011000111101100011110110000000000000000000000011110110001111011000000000000000000000000000000000111011100011101110001110111000111011100000000000001110111000111011100011101110000000000000000000000011101110001110111000000000000000000000000000000000110111100011011110001101111000110111100000000000001101111000110111100011011110000000000000000000000011011110001101111000000000000000000000000000000000011110100001111010000111101000011110100000000000000111101000011110100001111010000000000000000000000001111010000111101000000000000000000000000000000000011101100001110110000111011000011101100000000000000111011000011101100001110110000000000000000000000001110110000111011000000000000000000000000000000000011011100001101110000110111000011011100000000000000110111000011011100001101110000000000000000000000001101110000110111000000000000000000000000000000000010111100001011110000101111000010111100000000000000101111000010111100001011110000000000000000000000001011110000101111000000000000000000000000000000011111100101111110010111111001011111100100000000000111111001011111100101111110010000000000000000000001111110010111111001000000000000000000000000000000011111001101111100110111110011011111001100000000000111110011011111001101111100110000000000000000000001111100110111110011000000000000000000000000000000011110011101111001110111100111011110011100000000000111100111011110011101111001110000000000000000000001111001110111100111000000000000000000000000000000011110001101111000110111100011011110001100000000000111100011011110001101111000110000000000000000000001111000110111100011000000000000000000000000000000011111000101111100010111110001011111000100000000000111110001011111000101111100010000000000000000000001111100010111110001000000000000000000000000000000001111100100111110010011111001001111100100000000000011111001001111100100111110010000000000000000000000111110010011111001000000000000000000000000000000001111001100111100110011110011001111001100000000000011110011001111001100111100110000000000000000000000111100110011110011000000000000000000000000000000001110011100111001110011100111001110011100000000000011100111001110011100111001110000000000000000000000111001110011100111000000000000000000000000000000001110001100111000110011100011001110001100000000000011100011001110001100111000110000000000000000000000111000110011100011000000000000000000000000000000001111000100111100010011110001001111000100000000000011110001001111000100111100010000000000000000000000111100010011110001000000000000000000000000000000000111100100011110010001111001000111100100000000000001111001000111100100011110010000000000000000000000011110010001111001000000000000000000000000000000000111001100011100110001110011000111001100000000000001110011000111001100011100110000000000000000000000011100110001110011000000000000000000000000000000000110011100011001110001100111000110011100000000000001100111000110011100011001110000000000000000000000011001110001100111000000000000000000000000000000000110001100011000110001100011000110001100000000000001100011000110001100011000110000000000000000000000011000110001100011000000000000000000000000000000000111000100011100010001110001000111000100000000000001110001000111000100011100010000000000000000000000011100010001110001000000000000000000000000000000000011100100001110010000111001000011100100000000000000111001000011100100001110010000000000000000000000001110010000111001000000000000000000000000000000000011001100001100110000110011000011001100000000000000110011000011001100001100110000000000000000000000001100110000110011000000000000000000000000000000000010011100001001110000100111000010011100000000000000100111000010011100001001110000000000000000000000001001110000100111000000000000000000000000000000000010001100001000110000100011000010001100000000000000100011000010001100001000110000000000000000000000001000110000100011000000000000000000000000000000000011000100001100010000110001000011000100000000000000110001000011000100001100010000000000000000000000001100010000110001000000000000000000000000000000"; } function S2() public pure returns (string memory) { return "000000000011111111011111111101111111110111111111010000000000111111101111111110111111111011111111101100000000001111110111111111011111111101111111110111000000000011111011111111101111111110111111111011110000000000000000000011111111011111111101111111110100000000000000000000111111101111111110111111111011000000000000000000001111110111111111011111111101110000000000000000000011111011111111101111111110111100000000000000000000000000000011111111011111111101000000000000000000000000000000111111101111111110110000000000000000000000000000001111110111111111011100000000000000000000000000000011111011111111101111000000000011111110011111111001111111100111111110010000000000111111001111111100111111110011111111001100000000001111100111111110011111111001111111100111000000000000000000001111111001111111100111111110010000000000000000000011111100111111110011111111001100000000000000000000111110011111111001111111100111000000000000000000000000000000111111100111111110010000000000000000000000000000001111110011111111001100000000000000000000000000000011111001111111100111000000000011111100011111110001111111000111111100010000000000111110001111111000111111100011111110001100000000000000000000111111000111111100011111110001000000000000000000001111100011111110001111111000110000000000000000000000000000001111110001111111000100000000000000000000000000000011111000111111100011000000000011111000011111100001111110000111111000010000000000000000000011111000011111100001111110000100000000000000000000000000000011111000011111100001"; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; library Figure5DigitLib { function S1() public pure returns (string memory) { return "000000000000000000010000000001000000000100000000000000000000000000001100000000110000000011000000000000000000000000000111000000011100000001110000000000000000000000000011110000001111000000111100000000000000000000000001111100000111110000011111000000000000000000000000111111000011111100001111110000000000000000000000011111110001111111000111111100000000000000000000001111111100111111110011111111000000000000000000000111111111011111111101111111110000000000000000000000000000010000000001000000000000000000000000000000000000001100000000110000000000000000000000000000000000000111000000011100000000000000000000000000000000000011110000001111000000000000000000000000000000000001111100000111110000000000000000000000000000000000111111000011111100000000000000000000000000000000011111110001111111000000000000000000000000000000001111111100111111110000000000000000000000000000000111111111011111111100000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000110000000011000000000000000000000000000000000000011100000001110000000000000000000000000000000000001111000000111100000000000000000000000000000000000111110000011111000000000000000000000000000000000011111100001111110000000000000000000000000000000001111111000111111100000000000000000000000000000000111111110011111111000000000000000000000000000000011111111101111111110000000000000000000000000000010000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000001111111100000000000000000000000000000000000000000111111111000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000111111110000000000000000000000000000000000000000011111111100000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000011111111000000000000000000000000000000000000000001111111110000000000"; } function S2() public pure returns (string memory) { return "000000000011111111101111111110111111111000000000000000000000111111110011111111001111111100000000000000000000001111111000111111100011111110000000000000000000000011111100001111110000111111000000000000000000000000111110000011111000001111100000000000000000000000001111000000111100000011110000000000000000000000000011100000001110000000111000000000000000000000000000110000000011000000001100000000000000000000000000001000000000100000000010000000000000000000000000000011111111101111111110000000000000000000000000000000111111110011111111000000000000000000000000000000001111111000111111100000000000000000000000000000000011111100001111110000000000000000000000000000000000111110000011111000000000000000000000000000000000001111000000111100000000000000000000000000000000000011100000001110000000000000000000000000000000000000110000000011000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000001111111110111111111000000000000000000000000000000011111111001111111100000000000000000000000000000000111111100011111110000000000000000000000000000000001111110000111111000000000000000000000000000000000011111000001111100000000000000000000000000000000000111100000011110000000000000000000000000000000000001110000000111000000000000000000000000000000000000011000000001100000000000000000000000000000000000000100000000010000000000000000000000000000011111111100000000000000000000000000000000000000000111111110000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001111111110000000000000000000000000000000000000000011111111000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000111111111000000000000000000000000000000000000000001111111100000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000010000000000000000000"; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; library Figure6DigitLib { function S1() public pure returns (string memory) { return "000000000000000000010000000001000000000100000000000000000000000000001100000000110000000011000000000000000000000000000111000000011100000001110000000000000000000000000011110000001111000000111100000000000000000000000001111100000111110000011111000000000000000000000000111111000011111100001111110000000000000000000000011111110001111111000111111100000000000000000000001111111100111111110011111111000000000000000000000111111111011111111101111111110000000000000000000000000000010000000001000000000000000000000000000000000000001100000000110000000000000000000000000000000000000111000000011100000000000000000000000000000000000011110000001111000000000000000000000000000000000001111100000111110000000000000000000000000000000000111111000011111100000000000000000000000000000000011111110001111111000000000000000000000000000000001111111100111111110000000000000000000000000000000111111111011111111100000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000110000000011000000000000000000000000000000000000011100000001110000000000000000000000000000000000001111000000111100000000000000000000000000000000000111110000011111000000000000000000000000000000000011111100001111110000000000000000000000000000000001111111000111111100000000000000000000000000000000111111110011111111000000000000000000000000000000011111111101111111110000000000000000000000000000010000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000001111111100000000000000000000000000000000000000000111111111000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000111111110000000000000000000000000000000000000000011111111100000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000011111111000000000000000000000000000000000000000001111111110000000000"; } function S2() public pure returns (string memory) { return "000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000001111110000111111000011111100000000000000000000000001111110000111111000011111100000000000000000000000001111110000111111000011111100000000000000000000001111111000111111100011111110000000000000000000000001111111000111111100011111110000000000000000000000111111110011111111001111111100000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000111110000011111000000000000000000000000000000000000111110000011111000000000000000000000000000000000000111110000011111000000000000000000000000000000000000111110000011111000000000000000000000000000000001111110000111111000000000000000000000000000000000001111110000111111000000000000000000000000000000000001111110000111111000000000000000000000000000000001111111000111111100000000000000000000000000000000001111111000111111100000000000000000000000000000000111111110011111111000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000111111000011111100000000000000000000000000000000000111111000011111100000000000000000000000000000000000111111000011111100000000000000000000000000000000111111100011111110000000000000000000000000000000000111111100011111110000000000000000000000000000000011111111001111111100000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000111111110000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000011111111000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000001111111100000000000"; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; library Figure7DigitLib { function S1() public pure returns (string memory) { return "000000000000000000001111111100111111110011111111000000000000000000000011111110001111111000111111100000000000000000000000111111000011111100001111110000000000000000000000001111100000111110000011111000000000000000000000000011110000001111000000111100000000000000000000000000111000000011100000001110000000000000000000000000000000000000111111110011111111000000000000000000000000000000001111111000111111100000000000000000000000000000000011111100001111110000000000000000000000000000000000111110000011111000000000000000000000000000000000001111000000111100000000000000000000000000000000000011100000001110000000000000000000000000000000000000000000000011111111000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000001110000000"; } function S2() public pure returns (string memory) { return "111111110011111111001111111100111111110011111111001111111000111111100011111110001111111000111111100011111100001111110000111111000011111100001111110000111110000011111000001111100000111110000011111000001111000000111100000011110000001111000000111100000011100000001110000000111000000011100000001110000000"; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; library Figure8DigitLib { function S1() public pure returns (string memory) { return "000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000001111110000111111000011111100000000000000000000000001111110000111111000011111100000000000000000000000001111110000111111000011111100000000000000000000001111111000111111100011111110000000000000000000000001111111000111111100011111110000000000000000000000111111110011111111001111111100000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000111110000011111000000000000000000000000000000000000111110000011111000000000000000000000000000000000000111110000011111000000000000000000000000000000000000111110000011111000000000000000000000000000000001111110000111111000000000000000000000000000000000001111110000111111000000000000000000000000000000000001111110000111111000000000000000000000000000000001111111000111111100000000000000000000000000000000001111111000111111100000000000000000000000000000000111111110011111111000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000111111000011111100000000000000000000000000000000000111111000011111100000000000000000000000000000000000111111000011111100000000000000000000000000000000111111100011111110000000000000000000000000000000000111111100011111110000000000000000000000000000000011111111001111111100000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000111111110000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000011111111000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000001111111100000000000"; } function S2() public pure returns (string memory) { return "000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000001111110000111111000011111100000000000000000000000001111110000111111000011111100000000000000000000000001111110000111111000011111100000000000000000000001111111000111111100011111110000000000000000000000001111111000111111100011111110000000000000000000000111111110011111111001111111100000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000111110000011111000000000000000000000000000000000000111110000011111000000000000000000000000000000000000111110000011111000000000000000000000000000000000000111110000011111000000000000000000000000000000001111110000111111000000000000000000000000000000000001111110000111111000000000000000000000000000000000001111110000111111000000000000000000000000000000001111111000111111100000000000000000000000000000000001111111000111111100000000000000000000000000000000111111110011111111000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000111111000011111100000000000000000000000000000000000111111000011111100000000000000000000000000000000000111111000011111100000000000000000000000000000000111111100011111110000000000000000000000000000000000111111100011111110000000000000000000000000000000011111111001111111100000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000111111110000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000011111111000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000001111111100000000000"; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; library Figure9DigitLib { function S1() public pure returns (string memory) { return "000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000000000001000000000100000000010000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000000000000110000000011000000001100000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000000000001110000000111000000011100000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000000001111000000111100000011110000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000000000111110000011111000001111100000000000000000000001111110000111111000011111100000000000000000000000001111110000111111000011111100000000000000000000000001111110000111111000011111100000000000000000000001111111000111111100011111110000000000000000000000001111111000111111100011111110000000000000000000000111111110011111111001111111100000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000000000001000000000100000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000000000000110000000011000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000000000001110000000111000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000000001111000000111100000000000000000000000000000000111110000011111000000000000000000000000000000000000111110000011111000000000000000000000000000000000000111110000011111000000000000000000000000000000000000111110000011111000000000000000000000000000000001111110000111111000000000000000000000000000000000001111110000111111000000000000000000000000000000000001111110000111111000000000000000000000000000000001111111000111111100000000000000000000000000000000001111111000111111100000000000000000000000000000000111111110011111111000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000100000000010000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000000000011000000001100000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000000000111000000011100000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000000000111100000011110000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000000011111000001111100000000000000000000000000000000111111000011111100000000000000000000000000000000000111111000011111100000000000000000000000000000000000111111000011111100000000000000000000000000000000111111100011111110000000000000000000000000000000000111111100011111110000000000000000000000000000000011111111001111111100000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000001110000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000000111110000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000001111110000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000111111110000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000011111111000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000001111111100000000000"; } function S2() public pure returns (string memory) { return "000000000011111111101111111110111111111000000000000000000000111111110011111111001111111100000000000000000000001111111000111111100011111110000000000000000000000011111100001111110000111111000000000000000000000000111110000011111000001111100000000000000000000000001111000000111100000011110000000000000000000000000011100000001110000000111000000000000000000000000000110000000011000000001100000000000000000000000000001000000000100000000010000000000000000000000000000011111111101111111110000000000000000000000000000000111111110011111111000000000000000000000000000000001111111000111111100000000000000000000000000000000011111100001111110000000000000000000000000000000000111110000011111000000000000000000000000000000000001111000000111100000000000000000000000000000000000011100000001110000000000000000000000000000000000000110000000011000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000001111111110111111111000000000000000000000000000000011111111001111111100000000000000000000000000000000111111100011111110000000000000000000000000000000001111110000111111000000000000000000000000000000000011111000001111100000000000000000000000000000000000111100000011110000000000000000000000000000000000001110000000111000000000000000000000000000000000000011000000001100000000000000000000000000000000000000100000000010000000000000000000000000000011111111100000000000000000000000000000000000000000111111110000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000011111100000000000000000000000000000000000000000000111110000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001111111110000000000000000000000000000000000000000011111111000000000000000000000000000000000000000000111111100000000000000000000000000000000000000000001111110000000000000000000000000000000000000000000011111000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000111111111000000000000000000000000000000000000000001111111100000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000010000000000000000000"; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; library FiguresDoubleDigitsLib { string public constant FS0S1 = "00000011100111001110011100000000000011100111001110000000000000000011100111000000000000000000000011100000000100001000010000100000000000000100001000010000000000000000000100001000000000000000000000000100"; string public constant FS0S2 = "01110011100111001110000000111001110011100000000000011100111000000000000000001110000000000000000000000010000100001000010000000001000010000100000000000000100001000000000000000000010000000000000000000000"; string public constant FS1S1 = "000011000110001100011000100001000011000110001100010000100001000011000110001000010000100001000011000100001110011100111001110010000100001110011100111001000010000100001110011100100001000010000100001110010000111101111011110111101000010000111101111011110100001000010000111101111010000100001000010000111101000111101111011110111101100011000111101111011110110001100011000111101111011000110001100011000111101100111101111011110111101110011100111101111011110111001110011100111101111011100111001110011100111101110001110011100111001110011000110001110011100111001100011000110001110011100110001100011000110001110011"; string public constant FS1S2 = "100011000110001100010000010001100011000100000000001000110001000000000000000100010000000000000000000011001110011100111001000001100111001110010000000000110011100100000000000000011001000000000000000000001110111101111011110100000111011110111101000000000011101111010000000000000001110100000000000000000000110111101111011110110000011011110111101100000000001101111011000000000000000110110000000000000000000010111101111011110111000001011110111101110000000000101111011100000000000000010111000000000000000000001001110011100111001100000100111001110011000000000010011100110000000000000001001100000000000000000000"; string public constant FS2S1 = "000001111011110111100000000000111001110011100000000000011000110001100000000000001000010000100000000000000111101111000000000000000011100111000000000000000001100011000000000000000000100001000000000000000000000000111101111000000000000000011100111000000000000000001100011000000000000000000100001000000000000001111000000000000000000000111000000000000000000000011000000000000000000000001000000000000000000000000000001111000000000000000000000111000000000000000000000011000000000000000000000001000000000000000000000000000001111000000000000000000000111000000000000000000000011000000000000000000000001000000000"; string public constant FS2S2 = "000000111101111011110000000000001110011100111000000000000011000110001100000000000000100001000010000000000011110111100000000000000000111001110000000000000000001100011000000000000000000010000100000000000000000000011110111100000000000000000111001110000000000000000001100011000000000000000000010000100000000000111100000000000000000000001110000000000000000000000011000000000000000000000000100000000000000000000000000111100000000000000000000001110000000000000000000000011000000000000000000000000100000000000000000000000000111100000000000000000000001110000000000000000000000011000000000000000000000000100000"; string public constant FS3S1 = FS2S1; string public constant FS3S2 = FS2S1; string public constant FS4S1 = "011010110101101011010000001101011010110100000000000110101101000000000000000001010010100101001010000000101001010010100000000000010100101000000000000000010010100101001010010000001001010010100100000000000100101001000000000000000"; string public constant FS4S2 = "0000011101111011110111101000001101111011110111101100000110011100111001110010000010001100011000110001000000000011101111011110100000000001101111011110110000000000110011100111001000000000010001100011000100000000000000011101111010000000000000001101111011000000000000000110011100100000000000000010001100010000000000000000000011101000000000000000000001101100000000000000000000110010000000000000000000010001"; string public constant FS5S1 = FS2S2; string public constant FS5S2 = FS3S2; string public constant FS6S1 = FS2S2; string public constant FS6S2 = "000000111001110011100000000000000000111001110000000000001110011100000000000000000000000000011100000000000000000111000000000000000001110000000000000000000000100001000010000000000000001000010000100000000000000010000100001000000000000100001000000000000000000001000010000000000000000000010000100000000000000000000001000010000000000000000000010000100000000000000000000100001000000000000100000000000000000000000001000000000000000000000000010000000000000000000000000001000000000000000000000000010000000000000000000000000100000000000000000000000000010000000000000000000000000100000000000000000000000001000000000000110000000000000000000000000000110000000000000000000000000000110000000000000110001100000000000000000000000110001100000000000000110001100000000000000000000000110001100000000000011000110001100000000000000110001100011000000"; string public constant FS7S1 = "0000011110111101111011110000000000011110111101111000000000000000011110111100000000000000000000011110000000000000000000000000000000111001110011100111000000000000111001110011100000000000000000111001110000000000000000000000111000000011000110001100011000000000000011000110001100000000000000000011000110000000000000000000000011000"; string public constant FS7S2 = "1111011110111101111011110111001110011100111001110011000110001100011000110001000010000100001000010000"; string public constant FS8S1 = "000000111001110011100000000000000000111001110000000000001110011100000000000000000110001100011000000000000001100011000110000000000000000000000111000000000000000001110000000000000000011100000000000000000000001000010000100000000000000010000100001000000000000000100001000010000000000001100000000000000000000000000001100000000000000000000000000001100000000000000110000000000000000000000000000110000000000000000000000000000110000000000000000010000100000000000000000000100001000000000000000000001000010000000000001000010000000000000000000010000100000000000000000000100001000000000000000001100011000000000000000000000001100011000000000000001100011000000000000000000000001100011000000000000100000000000000000000000001000000000000000000000000010000000000000000000000000001000000000000000000000000010000000000000000000000000100000000000000000000000000010000000000000000000000000100000000000000000000000001000000"; string public constant FS8S2 = FS8S1; string public constant FS9S1 = "000000111001110011100000000000011100111000000000000000000000011100111000000000000111000000000000000000000000000111000000000000000000000000000111000000000000100001000010000000000000001000010000100000000000000010000100001000000000000000001000010000000000000000000010000100000000000000000000100001000000000000100001000000000000000000001000010000000000000000000010000100000000000000000000000000010000000000000000000000000100000000000000000000000001000000000000000001000000000000000000000000010000000000000000000000000100000000000000000100000000000000000000000001000000000000000000000000010000000000000000000000000000000011000000000000000000110000000000000000001100000000000000000000000000000000001100000000000000000011000000000000000000110000000000000000000000000001100011000000000000011000110000000000000000000000001100011000000000000011000110000000000000000011000110001100000000000000110001100011000000"; string public constant FS9S2 = FS2S1; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; import "./digits/FiguresDoubleDigitsLib.sol"; import "./FiguresUtilLib.sol"; library FiguresDoubles { function chooseStringsDoubles( uint8 number, uint8 index1, uint8 index2 ) public pure returns (bool[][2] memory b) { FiguresUtilLib.FigStrings memory strings = getFigStringsDoubles(number); return FiguresUtilLib._chooseStringsDouble( number, strings.s1, strings.s2, index1, index2 ); } function getFigStringsDoubles(uint8 number) private pure returns (FiguresUtilLib.FigStrings memory) { FiguresUtilLib.FigStrings memory figStrings; do { if (number == 0) { figStrings.s1 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS0S1, 8 ); figStrings.s2 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS0S2, 8 ); break; } if (number == 1) { figStrings.s1 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS1S1, 24 ); figStrings.s2 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS1S2, 24 ); break; } if (number == 2) { figStrings.s1 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS2S1, 24 ); figStrings.s2 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS2S2, 24 ); break; } if (number == 3) { figStrings.s1 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS3S1, 24 ); figStrings.s2 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS3S2, 24 ); break; } if (number == 4) { figStrings.s1 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS4S1, 9 ); figStrings.s2 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS4S2, 16 ); break; } if (number == 5) { figStrings.s1 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS5S1, 24 ); figStrings.s2 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS5S2, 24 ); break; } if (number == 6) { figStrings.s1 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS6S1, 24 ); figStrings.s2 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS6S2, 33 ); break; } if (number == 7) { figStrings.s1 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS7S1, 13 ); figStrings.s2 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS7S2, 4 ); break; } if (number == 8) { figStrings.s1 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS8S1, 36 ); figStrings.s2 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS8S2, 36 ); break; } if (number == 9) { figStrings.s1 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS9S1, 36 ); figStrings.s2 = FiguresUtilLib._assignValuesDouble( FiguresDoubleDigitsLib.FS9S2, 24 ); break; } } while (false); return figStrings; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; library FiguresRenderLib { function _concat(string memory a, string memory b) private pure returns (string memory) { return string(abi.encodePacked(a, b)); } function _generateRect( uint256 x, uint256 y, uint256 width, uint256 height, string memory color, string memory style ) public pure returns (string memory) { string memory s = ""; s = _concat(s, "<rect x='"); s = _concat(s, Strings.toString(x)); s = _concat(s, "' y='"); s = _concat(s, Strings.toString(y)); s = _concat(s, "' width='"); s = _concat(s, Strings.toString(width)); s = _concat(s, "' height='"); s = _concat(s, Strings.toString(height)); s = _concat(s, "' style='fill:rgb("); s = _concat(s, color); s = _concat(s, "); "); s = _concat(s, style); s = _concat(s, "'/>"); return s; } function _generatePixelSVG( uint256 x, uint256 y, uint256 factor, string memory color ) public pure returns (string memory) { string memory s = ""; s = _concat(s, "<rect x='"); s = _concat(s, Strings.toString(x)); s = _concat(s, "' y='"); s = _concat(s, Strings.toString(y)); s = _concat(s, "' width='"); s = _concat(s, Strings.toString(factor)); s = _concat(s, "' height='"); s = _concat(s, Strings.toString(factor)); s = _concat(s, "' style='fill:rgb("); s = _concat(s, color); s = _concat(s, "); mix-blend-mode: multiply;'/>"); return s; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; import "./digits/Figure0DigitLib.sol"; import "./digits/Figure1DigitLib.sol"; import "./digits/Figure2DigitLib.sol"; import "./digits/Figure3DigitLib.sol"; import "./digits/Figure4DigitLib.sol"; import "./digits/Figure5DigitLib.sol"; import "./digits/Figure6DigitLib.sol"; import "./digits/Figure7DigitLib.sol"; import "./digits/Figure8DigitLib.sol"; import "./digits/Figure9DigitLib.sol"; import "./FiguresUtilLib.sol"; library FiguresSingles { function chooseStringsSingles( uint8 number, uint8 index1, uint8 index2 ) public pure returns (bool[][2] memory b) { FiguresUtilLib.FigStrings memory strings = getFigStringsSingles(number); return FiguresUtilLib._chooseStringsSingle( number, strings.s1, strings.s2, index1, index2 ); } function getFigStringsSingles(uint8 number) private pure returns (FiguresUtilLib.FigStrings memory) { FiguresUtilLib.FigStrings memory figStrings; do { if (number == 0) { figStrings.s1 = FiguresUtilLib._assignValuesSingle( Figure0DigitLib.S1(), 144 ); figStrings.s2 = FiguresUtilLib._assignValuesSingle( Figure0DigitLib.S2(), 144 ); break; } if (number == 1) { figStrings.s1 = FiguresUtilLib._assignValuesSingle( Figure1DigitLib.S1(), 28 ); figStrings.s2 = FiguresUtilLib._assignValuesSingle( Figure1DigitLib.S2(), 28 ); break; } if (number == 2) { figStrings.s1 = FiguresUtilLib._assignValuesSingle( Figure2DigitLib.S1(), 54 ); figStrings.s2 = FiguresUtilLib._assignValuesSingle( Figure2DigitLib.S2(), 54 ); break; } if (number == 3) { figStrings.s1 = FiguresUtilLib._assignValuesSingle( Figure3DigitLib.S1(), 54 ); figStrings.s2 = FiguresUtilLib._assignValuesSingle( Figure3DigitLib.S2(), 54 ); break; } if (number == 4) { figStrings.s1 = FiguresUtilLib._assignValuesSingle( Figure4DigitLib.S1(), 108 ); figStrings.s2 = FiguresUtilLib._assignValuesSingle( Figure4DigitLib.S2(), 30 ); break; } if (number == 5) { figStrings.s1 = FiguresUtilLib._assignValuesSingle( Figure5DigitLib.S1(), 54 ); figStrings.s2 = FiguresUtilLib._assignValuesSingle( Figure5DigitLib.S2(), 54 ); break; } if (number == 6) { figStrings.s1 = FiguresUtilLib._assignValuesSingle( Figure6DigitLib.S1(), 54 ); figStrings.s2 = FiguresUtilLib._assignValuesSingle( Figure6DigitLib.S2(), 216 ); break; } if (number == 7) { figStrings.s1 = FiguresUtilLib._assignValuesSingle( Figure7DigitLib.S1(), 18 ); figStrings.s2 = FiguresUtilLib._assignValuesSingle( Figure7DigitLib.S2(), 6 ); break; } if (number == 8) { figStrings.s1 = FiguresUtilLib._assignValuesSingle( Figure8DigitLib.S1(), 216 ); figStrings.s2 = FiguresUtilLib._assignValuesSingle( Figure8DigitLib.S2(), 216 ); break; } if (number == 9) { figStrings.s1 = FiguresUtilLib._assignValuesSingle( Figure9DigitLib.S1(), 216 ); figStrings.s2 = FiguresUtilLib._assignValuesSingle( Figure9DigitLib.S2(), 54 ); break; } } while (false); return figStrings; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; library FiguresUtilLib { struct FigStrings { string[] s1; string[] s2; } function substring( string memory str, uint256 startIndex, uint256 endIndex ) public pure returns (string memory) { bytes memory strBytes = bytes(str); bytes memory result = new bytes(endIndex - startIndex); for (uint256 i = startIndex; i < endIndex; i++) { result[i - startIndex] = strBytes[i]; } return string(result); } function _assignValuesSingle(string memory input, uint16 size) internal pure returns (string[] memory) { return _assignValues(input, size, 50); } function _assignValuesDouble(string memory input, uint16 size) internal pure returns (string[] memory) { return _assignValues(input, size, 25); } function _assignValues( string memory input, uint16 size, uint8 length ) internal pure returns (string[] memory) { string[] memory output = new string[](size); for (uint256 i = 0; i < size; i++) { output[i] = substring(input, i * length, i * length + length); } return output; } function _chooseStringsSingle( uint8 number, string[] memory strings1, string[] memory strings2, uint8 index1, uint8 index2 ) internal pure returns (bool[][2] memory b) { return _chooseStrings(number, strings1, strings2, index1, index2, 50); } function _chooseStringsDouble( uint8 number, string[] memory strings1, string[] memory strings2, uint8 index1, uint8 index2 ) internal pure returns (bool[][2] memory b) { return _chooseStrings(number, strings1, strings2, index1, index2, 25); } function _chooseStrings( uint8 number, string[] memory strings1, string[] memory strings2, uint8 index1, uint8 index2, uint8 length ) private pure returns (bool[][2] memory b) { string[2] memory s; // some arrays are shorter than the random number generated uint256 availableIndex1 = index1 % strings1.length; uint256 availableIndex2 = index2 % strings2.length; s[0] = strings1[availableIndex1]; s[1] = strings2[availableIndex2]; // Special cases for 0, 1, 7 if (number == 0 || number == 1 || number == 7) { if (length == 25) { while ( keccak256(bytes(substring(s[0], 20, 24))) != keccak256(bytes(substring(s[1], 0, 4))) ) { uint256 is2 = ((availableIndex2 + availableIndex1++) % strings2.length); s[1] = strings2[is2]; } } if (length == 50) { while ( keccak256(bytes(substring(s[0], 40, 49))) != keccak256(bytes(substring(s[1], 0, 9))) ) { uint256 is2 = ((availableIndex2 + availableIndex1++) % strings2.length); s[1] = strings2[is2]; } } } b[0] = _returnBoolArray(s[0]); b[1] = _returnBoolArray(s[1]); return b; } function checkString(string memory s1, string memory s2) private pure {} function _returnBoolArray(string memory s) internal pure returns (bool[] memory) { bytes memory b = bytes(s); bool[] memory a = new bool[](b.length); for (uint256 i = 0; i < b.length; i++) { uint8 z = (uint8(b[i])); if (z == 48) { a[i] = true; } else if (z == 49) { a[i] = false; } } return a; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; interface IFiguresToken { /** * Initialize seed random variables used to render token * Can only be called by controller */ function initializeSeed(uint256[] memory seed) external; /** * Mint a token with the given seed. * Can only be called by controller */ function mint( uint256 tokenId, uint256 seed, address recipient ) external; /** * Render token based on seed */ function render(uint256 seed, uint256 assetId) external view returns (string memory s); }
{ "optimizer": { "enabled": true, "runs": 5 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": { "contracts/FiguresDoubles.sol": { "FiguresDoubles": "0x119d6f3f921b774f46e06bd4656715e184d7c69a" }, "contracts/FiguresRenderLib.sol": { "FiguresRenderLib": "0x631dbcb629e85b5c5f2c23138596f212e5b6c460" }, "contracts/FiguresSingles.sol": { "FiguresSingles": "0xdfbdb7b2f45671bce9cce07a36b1f129f3ace0eb" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"AdminApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"AdminRevoked","type":"event"},{"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":"address","name":"extension","type":"address"}],"name":"ApproveTransferUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address payable[]","name":"receivers","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"basisPoints","type":"uint256[]"}],"name":"DefaultRoyaltiesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"extension","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"ExtensionApproveTransferUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"extension","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"ExtensionBlacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"extension","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"ExtensionRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"extension","type":"address"},{"indexed":false,"internalType":"address payable[]","name":"receivers","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"basisPoints","type":"uint256[]"}],"name":"ExtensionRoyaltiesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"extension","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"ExtensionUnregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"extension","type":"address"},{"indexed":true,"internalType":"address","name":"permissions","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"MintPermissionsUpdated","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":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address payable[]","name":"receivers","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"basisPoints","type":"uint256[]"}],"name":"RoyaltiesUpdated","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":"CONTROLLER_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"approveAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"extension","type":"address"}],"name":"blacklistExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAdmins","outputs":[{"internalType":"address[]","name":"admins","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getApproveTransfer","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":[],"name":"getControllerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExtensions","outputs":[{"internalType":"address[]","name":"extensions","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getFeeBps","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getFeeRecipients","outputs":[{"internalType":"address payable[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getFees","outputs":[{"internalType":"address payable[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getRoyalties","outputs":[{"internalType":"address payable[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"seed","type":"uint256[]"}],"name":"initializeSeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"isAdmin","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":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mintBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"string","name":"uri","type":"string"}],"name":"mintBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"string[]","name":"uris","type":"string[]"}],"name":"mintBaseBatch","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint16","name":"count","type":"uint16"}],"name":"mintBaseBatch","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mintExtension","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"string","name":"uri","type":"string"}],"name":"mintExtension","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"string[]","name":"uris","type":"string[]"}],"name":"mintExtensionBatch","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint16","name":"count","type":"uint16"}],"name":"mintExtensionBatch","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"nonpayable","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":[{"internalType":"address","name":"extension","type":"address"},{"internalType":"string","name":"baseURI","type":"string"}],"name":"registerExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"extension","type":"address"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"bool","name":"baseURIIdentical","type":"bool"}],"name":"registerExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"assetId","type":"uint256"}],"name":"render","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"revokeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"value","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":"address","name":"extension","type":"address"}],"name":"setApproveTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setApproveTransferExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"}],"name":"setBaseTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"}],"name":"setBaseTokenURIExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"},{"internalType":"bool","name":"identical","type":"bool"}],"name":"setBaseTokenURIExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"controllerAddress","type":"address"}],"name":"setControllerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"extension","type":"address"},{"internalType":"address","name":"permissions","type":"address"}],"name":"setMintPermissions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address payable[]","name":"receivers","type":"address[]"},{"internalType":"uint256[]","name":"basisPoints","type":"uint256[]"}],"name":"setRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable[]","name":"receivers","type":"address[]"},{"internalType":"uint256[]","name":"basisPoints","type":"uint256[]"}],"name":"setRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"extension","type":"address"},{"internalType":"address payable[]","name":"receivers","type":"address[]"},{"internalType":"uint256[]","name":"basisPoints","type":"uint256[]"}],"name":"setRoyaltiesExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"uri","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string[]","name":"uris","type":"string[]"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string[]","name":"uris","type":"string[]"}],"name":"setTokenURIExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"uri","type":"string"}],"name":"setTokenURIExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"prefix","type":"string"}],"name":"setTokenURIPrefix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"prefix","type":"string"}],"name":"setTokenURIPrefixExtension","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":"tokenExtension","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenNumber","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"extension","type":"address"}],"name":"unregisterExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6000600a81905560a0604081905260808290526200002191601a9190620001af565b506014601b5560405180606001604052806040518060400160405280600b81526020016a3235352c3132302c32313160a81b81525081526020016040518060400160405280600981526020016803235352c3232372c360bc1b81525081526020016040518060400160405280600a81526020016932352c3138302c32353560b01b815250815250601c906003620000ba9291906200023e565b50348015620000c857600080fd5b50604051806040016040528060078152602001664669677572657360c81b8152506040518060400160405280600381526020016246494760e81b8152508181620001216200011b6200015b60201b60201c565b6200015f565b6001805581516200013a906004906020850190620001af565b50805162000150906005906020840190620001af565b505050505062000348565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b828054620001bd906200030b565b90600052602060002090601f016020900481019282620001e157600085556200022c565b82601f10620001fc57805160ff19168380011785556200022c565b828001600101855582156200022c579182015b828111156200022c5782518255916020019190600101906200020f565b506200023a92915062000291565b5090565b826003810192821562000283579160200282015b8281111562000283578251805162000272918491602090910190620001af565b509160200191906001019062000252565b506200023a929150620002a8565b5b808211156200023a576000815560010162000292565b808211156200023a576000620002bf8282620002c9565b50600101620002a8565b508054620002d7906200030b565b6000825580601f10620002e8575050565b601f01602090049060005260206000209081019062000308919062000291565b50565b600181811c908216806200032057607f821691505b602082108114156200034257634e487b7160e01b600052602260045260246000fd5b50919050565b615f0b80620003586000396000f3fe608060405234801561001057600080fd5b50600436106102eb5760003560e01c806301ffc9a7146102f057806302e7afb71461031857806306fdde031461032d578063081812fc14610342578063095ea7b3146103625780630ebd4c7f14610375578063162094c4146103955780631ebdc96a146103a857806320e4afe2146103bb57806322f374d0146103ce578063239be317146103df57806323b872dd146103f257806324d7806c146104055780632928ca58146104185780632a55205a146104395780632d3456701461045a57806330176e131461046d5780633071a0f91461048057806331ae450b14610493578063332dd1ae146104a857806338e52e78146104bb5780633e6134b8146104ce5780633f0f37f6146104e157806342842e0e146104f457806342966c6814610507578063596798ad1461051a57806361e5bc6b1461052d5780636352211e1461054057806366d1e9d0146105535780636d73e6691461056657806370a0823114610579578063715018a61461058c57806372ff03d3146105945780637884af44146105a75780637aa15f16146105ba57806382dcc0c8146105cd57806383b7db63146105e05780638c02cf30146105e85780638da5cb5b146105fb57806395d89b411461060357806399e0dd7c1461060b578063a22cb4651461061e578063aafb2d4414610631578063ac0c8cfa14610644578063ad2d0ddd14610657578063b0fe87c91461066a578063b88d4fde1461067d578063b98e631d14610690578063b9c4d9fb146106a3578063bb3bafd6146106c3578063c57380a2146106e4578063c87b56dd146106f5578063ce8aee9d14610708578063d5a06d4c146106c3578063ddbd273b1461071b578063e00aab4b14610740578063e7d3fe6b14610753578063e92a89f614610766578063e985e9c514610779578063f0cdc4991461078c578063f14210a61461079f578063f2fde38b146107b2578063f3d3d448146107c5578063fe2e1f58146107d8578063ffa1ad74146107eb575b600080fd5b6103036102fe366004614ac7565b6107f3565b60405190151581526020015b60405180910390f35b61032b610326366004614af9565b610822565b005b610335610877565b60405161030f9190614b6e565b610355610350366004614b81565b610909565b60405161030f9190614b9a565b61032b610370366004614bae565b610930565b610388610383366004614b81565b610a46565b60405161030f9190614c15565b61032b6103a3366004614c69565b610a76565b61032b6103b6366004614db0565b610ac1565b61032b6103c9366004614e28565b610daa565b600b546001600160a01b0316610355565b6103556103ed366004614b81565b610e23565b61032b610400366004614ea1565b610e53565b610303610413366004614af9565b610e84565b61042b610426366004614af9565b610eb3565b60405190815260200161030f565b61044c610447366004614ee2565b610f08565b60405161030f929190614f04565b61032b610468366004614af9565b610f46565b61032b61047b366004614f1d565b610fa3565b61032b61048e366004614f5e565b611022565b61049b611078565b60405161030f9190614f99565b61032b6104b6366004614fe6565b611126565b6103886104c9366004615051565b61117a565b61032b6104dc366004614f1d565b61128e565b61032b6104ef3660046150a6565b6112a2565b61032b610502366004614ea1565b6112f7565b61032b610515366004614b81565b611312565b61032b610528366004614af9565b6113b8565b61032b61053b36600461510d565b611401565b61035561054e366004614b81565b611483565b61032b610561366004614f1d565b6114b8565b61032b610574366004614af9565b6114ca565b61042b610587366004614af9565b611522565b61032b6115a8565b61042b6105a2366004614af9565b6115bc565b61042b6105b5366004614f5e565b61163f565b6103886105c8366004615051565b6116f5565b61032b6105db366004615168565b611835565b61049b611848565b6103356105f6366004614ee2565b6118e8565b610355611e9e565b610335611ead565b61032b610619366004614f1d565b611ebc565b61032b61062c3660046151be565b611f06565b61032b61063f36600461510d565b611f11565b61032b6106523660046151f7565b611fcb565b610388610665366004615214565b611fdd565b61032b610678366004615249565b6120ef565b61032b61068b3660046152af565b61213c565b601954610355906001600160a01b031681565b6106b66106b1366004614b81565b61216e565b60405161030f9190615391565b6106d66106d1366004614b81565b61219e565b60405161030f9291906153a4565b6019546001600160a01b0316610355565b610335610703366004614b81565b6121d8565b61032b610716366004614af9565b6121fc565b61072e610729366004614b81565b612245565b60405160ff909116815260200161030f565b61038861074e366004615214565b612271565b61032b6107613660046153d2565b612340565b61032b610774366004614c69565b612385565b610303610787366004615400565b612398565b61032b61079a366004615400565b6123c6565b61032b6107ad366004614b81565b612410565b61032b6107c0366004614af9565b612445565b61032b6107d3366004614af9565b6124bb565b61042b6107e6366004614f5e565b6124e5565b61042b600281565b60006107fe82612557565b8061080d575061080d8261257c565b8061081c575061081c826125b7565b92915050565b3361082b611e9e565b6001600160a01b0316148061084657506108466002336125ec565b61086b5760405162461bcd60e51b81526004016108629061542e565b60405180910390fd5b61087481612608565b50565b60606004805461088690615472565b80601f01602080910402602001604051908101604052809291908181526020018280546108b290615472565b80156108ff5780601f106108d4576101008083540402835291602001916108ff565b820191906000526020600020905b8154815290600101906020018083116108e257829003601f168201915b5050505050905090565b600061091482612702565b506000908152600860205260409020546001600160a01b031690565b600061093b82611483565b9050806001600160a01b0316836001600160a01b031614156109a95760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610862565b336001600160a01b03821614806109c557506109c58133612398565b610a375760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c00006064820152608401610862565b610a418383612727565b505050565b6060610a5182612795565b610a6d5760405162461bcd60e51b8152600401610862906154ad565b61081c826127b2565b33610a7f611e9e565b6001600160a01b03161480610a9a5750610a9a6002336125ec565b610ab65760405162461bcd60e51b81526004016108629061542e565b610a418383836127bd565b6019546001600160a01b03163314610aeb5760405162461bcd60e51b8152600401610862906154d8565b6040518060e00160405280610b1b606484600081518110610b0e57610b0e615503565b6020026020010151612825565b60ff1681526020016040518060800160405280610b46601486600181518110610b0e57610b0e615503565b60ff1660ff168152602001610b69601486600281518110610b0e57610b0e615503565b60ff1660ff168152602001610b8c601486600381518110610b0e57610b0e615503565b60ff1660ff168152602001610baf601486600481518110610b0e57610b0e615503565b60ff1660ff1681525081526020016040518060800160405280610be0601486600581518110610b0e57610b0e615503565b60ff1660ff168152602001610c03601486600681518110610b0e57610b0e615503565b60ff1660ff168152602001610c26601486600781518110610b0e57610b0e615503565b60ff1660ff168152602001610c49601486600881518110610b0e57610b0e615503565b60ff1660ff168152508152602001610c7061016884600981518110610b0e57610b0e615503565b60ff168152602001610c9161016884600a81518110610b0e57610b0e615503565b60ff168152602001610cb261016884600b81518110610b0e57610b0e615503565b60ff168152602001610cd361016884600c81518110610b0e57610b0e615503565b60ff168152506020600083600081518110610cf057610cf0615503565b6020908102919091018101518252818101929092526040016000208251815460ff191660ff90911617815590820151610d2f90600183019060046148b2565b506040820151610d4590600283019060046148b2565b50606082015160039091018054608084015160a085015160c09095015160ff90811663010000000263ff0000001996821662010000029690961663ffff0000199282166101000261ffff19909416919095161791909117169190911791909117905550565b33610db3611e9e565b6001600160a01b03161480610dce5750610dce6002336125ec565b610dea5760405162461bcd60e51b81526004016108629061542e565b610df385612795565b610e0f5760405162461bcd60e51b8152600401610862906154ad565b610e1c8585858585612885565b5050505050565b6000610e2e82612795565b610e4a5760405162461bcd60e51b8152600401610862906154ad565b61081c8261290c565b610e5d3382612997565b610e795760405162461bcd60e51b815260040161086290615519565b610a418383836129f6565b6000816001600160a01b0316610e98611e9e565b6001600160a01b0316148061081c575061081c6002836125ec565b600060026001541415610ed85760405162461bcd60e51b815260040161086290615567565b6002600155610ee5612b8b565b610efe8260405180602001604052806000815250612be1565b6001805592915050565b600080610f1484612795565b610f305760405162461bcd60e51b8152600401610862906154ad565b610f3a8484612c59565b915091505b9250929050565b610f4e612d2c565b610f596002826125ec565b156108745760405133906001600160a01b038316907f7c0c3c84c67c85fcac635147348bfe374c24a1a93d0366d1cfe9d8853cbf89d590600090a3610f9f600282612d8b565b5050565b33610fac611e9e565b6001600160a01b03161480610fc75750610fc76002336125ec565b610fe35760405162461bcd60e51b81526004016108629061542e565b610f9f82828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612da092505050565b3361102b611e9e565b6001600160a01b0316148061104657506110466002336125ec565b6110625760405162461bcd60e51b81526004016108629061542e565b61106b83612ddc565b610a418383836000612e04565b60606110846002612ef5565b6001600160401b0381111561109b5761109b614cb4565b6040519080825280602002602001820160405280156110c4578160200160208202803683370190505b50905060005b6110d46002612ef5565b811015611122576110e6600282612eff565b8282815181106110f8576110f8615503565b6001600160a01b03909216602092830291909101909101528061111a816155b4565b9150506110ca565b5090565b3361112f611e9e565b6001600160a01b0316148061114a575061114a6002336125ec565b6111665760405162461bcd60e51b81526004016108629061542e565b611174600085858585612f0b565b50505050565b60606002600154141561119f5760405162461bcd60e51b815260040161086290615567565b60026001556111ac612b8b565b816001600160401b038111156111c4576111c4614cb4565b6040519080825280602002602001820160405280156111ed578160200160208202803683370190505b50905060005b828110156112825761125d8585858481811061121157611211615503565b905060200281019061122391906155cf565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612be192505050565b82828151811061126f5761126f615503565b60209081029190910101526001016111f3565b50600180559392505050565b611296612b8b565b610f9f82826000612ff8565b336112ab611e9e565b6001600160a01b031614806112c657506112c66002336125ec565b6112e25760405162461bcd60e51b81526004016108629061542e565b6112eb84612ddc565b61117484848484612e04565b610a418383836040518060200160405280600081525061213c565b600260015414156113355760405162461bcd60e51b815260040161086290615567565b60026001556113443382612997565b6113905760405162461bcd60e51b815260206004820181905260248201527f43616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610862565b600061139b82611483565b90506113a682613035565b6113b081836130ca565b505060018055565b336113c1611e9e565b6001600160a01b031614806113dc57506113dc6002336125ec565b6113f85760405162461bcd60e51b81526004016108629061542e565b610874816131dd565b611409612b8b565b825181146114295760405162461bcd60e51b815260040161086290615615565b60005b83518110156111745761147b84828151811061144a5761144a615503565b602002602001015184848481811061146457611464615503565b905060200281019061147691906155cf565b613233565b60010161142c565b6000818152600660205260408120546001600160a01b03168061081c5760405162461bcd60e51b81526004016108629061563c565b6114c0612b8b565b610f9f8282613269565b6114d2612d2c565b6114dd6002826125ec565b6108745760405133906001600160a01b038316907f7e1a1a08d52e4ba0e21554733d66165fd5151f99460116223d9e3a608eec5cb190600090a3610f9f600282613283565b60006001600160a01b03821661158c5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610862565b506001600160a01b031660009081526007602052604090205490565b6115b0612d2c565b6115ba6000613298565b565b6000600260015414156115e15760405162461bcd60e51b815260040161086290615567565b6002600155336115ef611e9e565b6001600160a01b0316148061160a575061160a6002336125ec565b6116265760405162461bcd60e51b81526004016108629061542e565b610efe82604051806020016040528060008152506132e8565b6000600260015414156116645760405162461bcd60e51b815260040161086290615567565b600260015533611672611e9e565b6001600160a01b0316148061168d575061168d6002336125ec565b6116a95760405162461bcd60e51b81526004016108629061542e565b6116e98484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506132e892505050565b60018055949350505050565b60606002600154141561171a5760405162461bcd60e51b815260040161086290615567565b600260015533611728611e9e565b6001600160a01b0316148061174357506117436002336125ec565b61175f5760405162461bcd60e51b81526004016108629061542e565b816001600160401b0381111561177757611777614cb4565b6040519080825280602002602001820160405280156117a0578160200160208202803683370190505b50905060005b8281101561128257611810858585848181106117c4576117c4615503565b90506020028101906117d691906155cf565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506132e892505050565b82828151811061182257611822615503565b60209081029190910101526001016117a6565b61183d612b8b565b610a41838383612ff8565b6060611854600c612ef5565b6001600160401b0381111561186b5761186b614cb4565b604051908082528060200260200182016040528015611894578160200160208202803683370190505b50905060005b6118a4600c612ef5565b811015611122576118b6600c82612eff565b8282815181106118c8576118c8615503565b6001600160a01b039092166020928302919091019091015260010161189a565b600082815260208080526040808320815160e081018352815460ff168152825160808101938490526060959486948594879493909284019160018401906004908288855b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161192c57505050928452505060408051608081019182905260209093019291506002840190600490826000855b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411611981575050509284525050506003919091015460ff80821660208085019190915261010083048216604080860191909152620100008404831660608601526301000000909304821660809094019390935283518251808401909352601883527719185d184e9a5b5859d94bdcdd99cade1b5b0edd5d198e0b60421b93830193909352919091169550909150611a4090849061330b565b9250611a64836040518060a0016040528060678152602001615db56067913961330b565b9250611a8683611a81601b54600a611a7c919061566e565b613337565b61330b565b9250611ab4836040518060400160405280600a81526020016927206865696768743d2760b01b81525061330b565b9250611acc83611a81601b54600a611a7c919061566e565b9250611af28360405180604001604052806002815260200161139f60f11b81525061330b565b9250611b0a83611a8183602001518460400151613434565b9250600a841015611bc8576060810151608082015160405163d92457e160e01b815260009273dfbdb7b2f45671bce9cce07a36b1f129f3ace0eb9263d92457e192611b5b928a92909160040161568d565b60006040518083038186803b158015611b7357600080fd5b505af4158015611b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611baf91908101906156aa565b9050611bc084611a81600084613712565b935050611d43565b6000611bd5600a866157b8565b90506000611be4600a876157cc565b9050600073119d6f3f921b774f46e06bd4656715e184d7c69a63fda13a3884866060015187608001516040518463ffffffff1660e01b8152600401611c2b9392919061568d565b60006040518083038186803b158015611c4357600080fd5b505af4158015611c57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c7f91908101906156aa565b9050600073119d6f3f921b774f46e06bd4656715e184d7c69a63fda13a38848760a001518860c001516040518463ffffffff1660e01b8152600401611cc69392919061568d565b60006040518083038186803b158015611cde57600080fd5b505af4158015611cf2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d1a91908101906156aa565b9050611d2b87611a81600085613712565b9650611d3c87611a81600184613712565b9650505050505b611d6b83604051806040016040528060068152602001651e17b9bb339f60d11b81525061330b565b9250611da3604051806040016040528060118152602001707b226e616d65223a22466967757265202360781b815250611a8188613337565b9150611dc7826040518060600160405280602b8152602001615d8a602b913961330b565b9150611dd682611a8186613337565b9150611dfa82604051806080016040528060468152602001615e3c6046913961330b565b9150611e0982611a8188613337565b9150611e2d82604051806060016040528060348152602001615ea26034913961330b565b9150611e3c82611a8186613337565b9150611e6e826040518060400160405280600e81526020016d113eae96101134b6b0b3b2911d1160911b81525061330b565b91508183604051602001611e839291906157e0565b60405160208183030381529060405294505050505092915050565b6000546001600160a01b031690565b60606005805461088690615472565b33611ec5611e9e565b6001600160a01b03161480611ee05750611ee06002336125ec565b611efc5760405162461bcd60e51b81526004016108629061542e565b610f9f82826138db565b610f9f33838361390f565b33611f1a611e9e565b6001600160a01b03161480611f355750611f356002336125ec565b611f515760405162461bcd60e51b81526004016108629061542e565b82518114611f715760405162461bcd60e51b815260040161086290615615565b60005b835181101561117457611fc3848281518110611f9257611f92615503565b6020026020010151848484818110611fac57611fac615503565b9050602002810190611fbe91906155cf565b6127bd565b600101611f74565b611fd3612b8b565b61087433826139da565b6060600260015414156120025760405162461bcd60e51b815260040161086290615567565b600260015533612010611e9e565b6001600160a01b0316148061202b575061202b6002336125ec565b6120475760405162461bcd60e51b81526004016108629061542e565b8161ffff166001600160401b0381111561206357612063614cb4565b60405190808252806020026020018201604052801561208c578160200160208202803683370190505b50905060005b8261ffff168161ffff1610156120e4576120bb84604051806020016040528060008152506132e8565b828261ffff16815181106120d1576120d1615503565b6020908102919091010152600101612092565b506001805592915050565b336120f8611e9e565b6001600160a01b0316148061211357506121136002336125ec565b61212f5760405162461bcd60e51b81526004016108629061542e565b610e1c8585858585612f0b565b6121463383612997565b6121625760405162461bcd60e51b815260040161086290615519565b61117484848484613a4f565b606061217982612795565b6121955760405162461bcd60e51b8152600401610862906154ad565b61081c82613a82565b6060806121aa83612795565b6121c65760405162461bcd60e51b8152600401610862906154ad565b6121cf83613a94565b91509150915091565b60606121e382612702565b6000828152601f602052604090205461081c90836118e8565b33612205611e9e565b6001600160a01b0316148061222057506122206002336125ec565b61223c5760405162461bcd60e51b81526004016108629061542e565b61087481613e51565b600061225082612702565b506000908152601f6020908152604080832054835290805290205460ff1690565b6060600260015414156122965760405162461bcd60e51b815260040161086290615567565b60026001556122a3612b8b565b8161ffff166001600160401b038111156122bf576122bf614cb4565b6040519080825280602002602001820160405280156122e8578160200160208202803683370190505b50905060005b8261ffff168161ffff1610156120e4576123178460405180602001604052806000815250612be1565b828261ffff168151811061232d5761232d615503565b60209081029190910101526001016122ee565b6019546001600160a01b0316331461236a5760405162461bcd60e51b8152600401610862906154d8565b6000838152601f60205260409020829055610a418184613e80565b61238d612b8b565b610a41838383613233565b6001600160a01b03918216600090815260096020908152604080832093909416825291909152205460ff1690565b336123cf611e9e565b6001600160a01b031614806123ea57506123ea6002336125ec565b6124065760405162461bcd60e51b81526004016108629061542e565b610f9f8282613fac565b612418612d2c565b604051339082156108fc029083906000818181858888f19350505050158015610f9f573d6000803e3d6000fd5b61244d612d2c565b6001600160a01b0381166124b25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610862565b61087481613298565b6124c3612d2c565b601980546001600160a01b0319166001600160a01b0392909216919091179055565b60006002600154141561250a5760405162461bcd60e51b815260040161086290615567565b6002600155612517612b8b565b6116e98484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612be192505050565b60006001600160e01b03198216639088c20760e01b148061081c575061081c826140e1565b60006001600160e01b031982166380ac58cd60e01b148061080d57506001600160e01b03198216635b5e139f60e01b148061081c575061081c825b60006001600160e01b03198216632a9f3abf60e11b148061081c57506301ffc9a760e01b6001600160e01b031983161461081c565b6000612601836001600160a01b038416614192565b9392505050565b6001600160a01b0381161580159061262957506001600160a01b0381163014155b6126715760405162461bcd60e51b815260206004820152601960248201527821b0b73737ba10313630b1b5b634b9ba103cb7bab939b2b63360391b6044820152606401610862565b61267c600c826125ec565b156126b25760405133906001600160a01b03831690600080516020615e1c83398151915290600090a36126b0600c82612d8b565b505b6126bd600e826125ec565b6108745760405133906001600160a01b038316907f05ac7bc5a606cd92a63365f9fda244499b9add0526b22d99937b6bd88181059c90600090a3610f9f600e82613283565b61270b81612795565b6108745760405162461bcd60e51b81526004016108629061563c565b600081815260086020526040902080546001600160a01b0319166001600160a01b038416908117909155819061275c82611483565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000908152600660205260409020546001600160a01b0316151590565b606061260182613a94565b6000831180156127cf5750600a548311155b80156127f057506000838152601260205260409020546001600160a01b0316155b61280c5760405162461bcd60e51b815260040161086290615848565b6000838152601660205260409020611174908383614941565b600082424433856040516020016128629493929190938452602084019290925260601b6001600160601b0319166040830152605482015260740190565b6040516020818303038152906040528051906020012060001c61260191906157cc565b612891848484846141aa565b60008581526018602052604081206128a8916149b5565b6128c784848484601860008b815260200190815260200160002061424f565b847fabb46fe0761d77584bde75697647804ffd8113abd4d8d06bc664150395eccdee858585856040516128fd949392919061586f565b60405180910390a25050505050565b6000818152601260205260409020546001600160a01b03168061296a5760405162461bcd60e51b815260206004820152601660248201527527379032bc3a32b739b4b7b7103337b9103a37b5b2b760511b6044820152606401610862565b612975600e826125ec565b156129925760405162461bcd60e51b8152600401610862906158f3565b919050565b6000806129a383611483565b9050806001600160a01b0316846001600160a01b031614806129ca57506129ca8185612398565b806129ee5750836001600160a01b03166129e384610909565b6001600160a01b0316145b949350505050565b826001600160a01b0316612a0982611483565b6001600160a01b031614612a6d5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610862565b6001600160a01b038216612acf5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610862565b612ada838383614312565b612ae5600082612727565b6001600160a01b0383166000908152600760205260408120805460019290612b0e908490615922565b90915550506001600160a01b0382166000908152600760205260408120805460019290612b3c908490615939565b909155505060008181526006602052604080822080546001600160a01b0319166001600160a01b038681169182179092559151849391871691600080516020615e8283398151915291a4505050565b612b96600c336125ec565b6115ba5760405162461bcd60e51b815260206004820152601c60248201527b26bab9ba103132903932b3b4b9ba32b932b21032bc3a32b739b4b7b760211b6044820152606401610862565b6000600a60008154612bf2906155b4565b9091555050600a54612c04838261431d565b600081815260126020526040902080546001600160a01b03191633179055612c2c83826143b1565b815115612c545760008181526016602090815260409091208351612c52928501906149d3565b505b61081c565b600080600080612c6886613a94565b91509150600182511115612cbd5760405162461bcd60e51b815260206004820152601c60248201527b26b7b932903a3430b71018903937bcb0b63a3c903932b1b2b4bb32b960211b6044820152606401610862565b8151612cd157306000935093505050610f3f565b81600081518110612ce457612ce4615503565b60200260200101516127108683600081518110612d0357612d03615503565b6020026020010151612d15919061566e565b612d1f91906157b8565b9350935050509250929050565b33612d35611e9e565b6001600160a01b0316146115ba5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610862565b6000612601836001600160a01b0384166143cb565b60008052601360209081528151610f9f917f8fa6efc3be94b5b348b21fea823fe8d100408cee9b7f90524494500445d8ff6c91908401906149d3565b612de7600e826125ec565b156108745760405162461bcd60e51b8152600401610862906158f3565b6001600160a01b0384163014801590612e2a5750612e2a846001600160a01b03166144be565b612e605760405162461bcd60e51b8152602060048201526007602482015266125b9d985b1a5960ca1b6044820152606401610862565b60405133906001600160a01b038616907fd8cb8ba4086944eabf43c5535b7712015e4d4c714b24bf812c040ea5b7a3e42a90600090a36001600160a01b0384166000908152601360205260409020612eb9908484614941565b506001600160a01b0384166000908152601460205260409020805460ff1916821515179055612ee9600c85613283565b506111748460016139da565b600061081c825490565b600061260183836144cd565b612f17848484846141aa565b6001600160a01b0385166000908152601760205260408120612f38916149b5565b612f6984848484601760008b6001600160a01b03166001600160a01b0316815260200190815260200160002061424f565b6001600160a01b038516612fb9577f2b6849d5976d799a5b0ca4dfd6b40a3d7afe9ea72c091fa01a958594f9a2659b84848484604051612fac949392919061586f565b60405180910390a1610e1c565b846001600160a01b03167f535a93d2cb000582c0ebeaa9be4890ec6a287f98eb2df00c54c300612fd78d8f858585856040516128fd949392919061586f565b336000908152601360205260409020613012908484614941565b50336000908152601460205260409020805460ff19169115159190911790555050565b600061304082611483565b905061304e81600084614312565b613059600083612727565b6001600160a01b0381166000908152600760205260408120805460019290613082908490615922565b909155505060008281526006602052604080822080546001600160a01b0319169055518391906001600160a01b03841690600080516020615e82833981519152908390a45050565b6000818152601260205260409020546001600160a01b03161561318757600081815260126020526040902054613110906001600160a01b03166311686e4b60e21b6144f7565b1561318757600081815260126020526040908190205490516311686e4b60e21b81526001600160a01b03909116906345a1b92c906131549085908590600401614f04565b600060405180830381600087803b15801561316e57600080fd5b505af1158015613182573d6000803e3d6000fd5b505050505b600081815260166020526040902080546131a090615472565b1590506131be5760008181526016602052604081206131be91614a47565b600090815260126020526040902080546001600160a01b031916905550565b600b80546001600160a01b0319166001600160a01b0383161790556040517f959c0e47a2fe3cf01e237ba4892e2cc3194d77cbfb33e434e40873225d6b595f90613228908390614b9a565b60405180910390a150565b6000838152601260205260409020546001600160a01b0316331461280c5760405162461bcd60e51b815260040161086290615848565b336000908152601560205260409020610a41908383614941565b6000612601836001600160a01b038416614513565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000600a600081546132f9906155b4565b9091555050600a54612c2c83826143b1565b60608282604051602001613320929190615951565b604051602081830303815290604052905092915050565b60608161335b5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613385578061336f816155b4565b915061337e9050600a836157b8565b915061335f565b6000816001600160401b0381111561339f5761339f614cb4565b6040519080825280601f01601f1916602001820160405280156133c9576020820181803683370190505b5090505b84156129ee576133de600183615922565b91506133eb600a866157cc565b6133f6906030615939565b60f81b81838151811061340b5761340b615503565b60200101906001600160f81b031916908160001a90535061342d600a866157b8565b94506133cd565b60408051602081019091526000808252606091905b600481101561370a576000600386836004811061346857613468615503565b60200201516134779190615980565b60ff1690506000600486846004811061349257613492615503565b60200201516134a19190615980565b60ff1690506134cb84604051806040016040528060038152602001621e339f60e91b81525061330b565b93506135d98473631dbcb629e85b5c5f2c23138596f212e5b6c460638d749263601b5460056002896134fd91906157cc565b613507919061566e565b613511919061566e565b601b54600561352160028b6157b8565b61352b919061566e565b613535919061566e565b601b5461354390600561566e565b601b5461355190600561566e565b601c8a6003811061356457613564615503565b016040518663ffffffff1660e01b8152600401613585959493929190615a42565b60006040518083038186803b15801561359d57600080fd5b505af41580156135b1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a819190810190615a8a565b935080600314156136135761360a84604051806040016040528060048152602001631e17b39f60e11b81525061330b565b935050506136f8565b6136cb8473631dbcb629e85b5c5f2c23138596f212e5b6c460638d749263601b54600560028961364391906157cc565b61364d919061566e565b613657919061566e565b601b54600561366760028b6157b8565b613671919061566e565b61367b919061566e565b601b5461368990600561566e565b601b5461369790600561566e565b601c89600381106136aa576136aa615503565b016040518663ffffffff1660e01b8152600401613585959493929190615af7565b93506136f384604051806040016040528060048152602001631e17b39f60e11b81525061330b565b935050505b80613702816155b4565b915050613449565b509392505050565b60606000831561372d57601b5461372a90600561566e565b90505b604080516020810190915260008082525b60028110156138d25760005b85826002811061375c5761375c615503565b6020020151518110156138bf576000600587846002811061377f5761377f615503565b60200201515161378f91906157b8565b90508683600281106137a3576137a3615503565b602002015182815181106137b9576137b9615503565b6020026020010151156137cc57506138af565b601b5480600087826137e160ff8716886157cc565b6137eb919061566e565b6137f59190615939565b9050600086600114156138105761380d83600561566e565b90505b8261381e60ff8716886157b8565b613828919061566e565b6138329082615939565b601b54604051635a696a6760e01b81526004810185905260248101839052604481019190915260806064820152600b60848201526a3235352c3132302c32313160a81b60a48201529091506138a790899073631dbcb629e85b5c5f2c23138596f212e5b6c46090635a696a679060c401613585565b975050505050505b6138b8816155b4565b905061374a565b50806138ca816155b4565b91505061373e565b50949350505050565b600080526015602052610a417fa31547ce6245cdb9ecea19cf8c7eb9f5974025bb4075011409251ae855b30aed8383614941565b816001600160a01b0316836001600160a01b0316141561396d5760405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b6044820152606401610862565b6001600160a01b03838116600081815260096020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6139eb826345ffcdad60e01b6144f7565b15610f9f576001600160a01b038216600081815260116020908152604091829020805460ff191685151590811790915591519182527f072a7592283e2c2d1d56d21517ff6013325e0f55483f4828373ff4d98b0a1a36910160405180910390a25050565b613a5a8484846129f6565b613a668484848461455d565b6111745760405162461bcd60e51b815260040161086290615b61565b6060613a8d82613a94565b5092915050565b606080600060186000858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015613b1657600084815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900461ffff1681830152825260019092019101613acc565b505050509050805160001415613c75576000848152601260205260409020546001600160a01b03168015613c7357613b5581634e53ee3d60e11b6144f7565b15613bef57604051634e53ee3d60e11b81526001600160a01b03821690639ca7dc7a90613b889030908990600401614f04565b60006040518083038186803b158015613ba057600080fd5b505afa158015613bb4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613bdc9190810190615c0e565b8151919550935015613bef575050915091565b6001600160a01b038116600090815260176020908152604080832080548251818502810185019093528083529193909284015b82821015613c6c57600084815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900461ffff1681830152825260019092019101613c22565b5050505091505b505b8051613d15576000808052601760209081527fd840e16649f6b9a295d95876f4633d3a6b10b55e8162971cf78afd886d5ec89b8054604080518285028101850190915281815293919290919084015b82821015613d0e57600084815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900461ffff1681830152825260019092019101613cc4565b5050505090505b805115613e4b5780516001600160401b03811115613d3557613d35614cb4565b604051908082528060200260200182016040528015613d5e578160200160208202803683370190505b50925080516001600160401b03811115613d7a57613d7a614cb4565b604051908082528060200260200182016040528015613da3578160200160208202803683370190505b50915060005b8151811015613e4957818181518110613dc457613dc4615503565b602002602001015160000151848281518110613de257613de2615503565b60200260200101906001600160a01b031690816001600160a01b031681525050818181518110613e1457613e14615503565b60200260200101516020015161ffff16838281518110613e3657613e36615503565b6020908102919091010152600101613da9565b505b50915091565b60405133906001600160a01b03831690600080516020615e1c83398151915290600090a3610f9f600c82612d8b565b6001600160a01b038216613ed65760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610862565b613edf81612795565b15613f2b5760405162461bcd60e51b815260206004820152601c60248201527b115490cdcc8c4e881d1bdad95b88185b1c9958591e481b5a5b9d195960221b6044820152606401610862565b613f3760008383614312565b6001600160a01b0382166000908152600760205260408120805460019290613f60908490615939565b909155505060008181526006602052604080822080546001600160a01b0319166001600160a01b0386169081179091559051839290600080516020615e82833981519152908290a45050565b613fb7600c836125ec565b6140035760405162461bcd60e51b815260206004820152601e60248201527f43726561746f72436f72653a20496e76616c696420657874656e73696f6e00006044820152606401610862565b6001600160a01b0381161580614025575061402581631e05385b60e31b6144f7565b6140635760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610862565b6001600160a01b03828116600090815260106020526040902054811690821614610f9f576001600160a01b0382811660008181526010602052604080822080546001600160a01b031916948616948517905551339392917f6a835c4fcf7e0d398db3762332fdaa1471814ad39f1e2d6d0b3fdabf8efee3e091a45050565b60006001600160e01b031982166314d9799760e21b148061411257506001600160e01b031982166328f10a2160e01b145b8061412157506141218261257c565b8061413c57506001600160e01b03198216635d9dd7eb60e11b145b8061415757506001600160e01b03198216632dde656160e21b145b8061417257506001600160e01b031982166335681b5360e21b145b8061081c57506001600160e01b0319821663152a902d60e11b1492915050565b60009081526001919091016020526040902054151590565b8281146141c95760405162461bcd60e51b815260040161086290615615565b6000805b82811015614203578383828181106141e7576141e7615503565b90506020020135826141f99190615939565b91506001016141cd565b506127108110610e1c5760405162461bcd60e51b8152602060048201526017602482015276496e76616c696420746f74616c20726f79616c7469657360481b6044820152606401610862565b60005b8281101561430a5781604051806040016040528088888581811061427857614278615503565b905060200201602081019061428d9190614af9565b6001600160a01b031681526020018686858181106142ad576142ad615503565b61ffff602091820293909301358316909352508354600181810186556000958652948390208451910180549490930151909116600160a01b026001600160b01b03199093166001600160a01b039091161791909117905501614252565b505050505050565b610a41838383614671565b336000908152601060205260409020546001600160a01b031615610f9f573360008181526010602052604090819020549051631e05385b60e31b815260048101929092526001600160a01b03848116602484015260448301849052169063f029c2d890606401600060405180830381600087803b15801561439d57600080fd5b505af115801561430a573d6000803e3d6000fd5b610f9f8282604051806020016040528060008152506147c3565b600081815260018301602052604081205480156144b45760006143ef600183615922565b855490915060009061440390600190615922565b905081811461446857600086600001828154811061442357614423615503565b906000526020600020015490508087600001848154811061444657614446615503565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061447957614479615cd2565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061081c565b600091505061081c565b6001600160a01b03163b151590565b60008260000182815481106144e4576144e4615503565b9060005260206000200154905092915050565b6000614502836147f6565b801561260157506126018383614829565b600061451f8383614192565b6145555750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561081c565b50600061081c565b6000614571846001600160a01b03166144be565b1561466657604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906145a8903390899088908890600401615ce8565b602060405180830381600087803b1580156145c257600080fd5b505af19250505080156145f2575060408051601f3d908101601f191682019092526145ef91810190615d25565b60015b61464c573d808015614620576040519150601f19603f3d011682016040523d82523d6000602084013e614625565b606091505b5080516146445760405162461bcd60e51b815260040161086290615b61565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506129ee565b506001949350505050565b6000818152601260209081526040808320546001600160a01b03168352601190915290205460ff161561477c5760008181526012602052604090819020549051632f3537c560e11b81526001600160a01b0390911690635e6a6f8a906146e1903390879087908790600401615d42565b602060405180830381600087803b1580156146fb57600080fd5b505af115801561470f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147339190615d6c565b610a415760405162461bcd60e51b815260206004820152601a602482015279457874656e73696f6e20617070726f76616c206661696c75726560301b6044820152606401610862565b600b546001600160a01b031615610a4157600b54604051632f3537c560e11b81526001600160a01b0390911690635e6a6f8a906146e1903390879087908790600401615d42565b6147cd8383613e80565b6147da600084848461455d565b610a415760405162461bcd60e51b815260040161086290615b61565b6000614809826301ffc9a760e01b614829565b801561081c5750614822826001600160e01b0319614829565b1592915050565b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b178152825160009392849283928392918391908a617530fa92503d9150600051905082801561489b575060208210155b80156148a75750600081115b979650505050505050565b6001830191839082156149355791602002820160005b8382111561490657835183826101000a81548160ff021916908360ff16021790555092602001926001016020816000010492830192600103026148c8565b80156149335782816101000a81549060ff0219169055600101602081600001049283019260010302614906565b505b50611122929150614a7d565b82805461494d90615472565b90600052602060002090601f01602090048101928261496f5760008555614935565b82601f106149885782800160ff19823516178555614935565b82800160010185558215614935579182015b8281111561493557823582559160200191906001019061499a565b50805460008255906000526020600020908101906108749190614a92565b8280546149df90615472565b90600052602060002090601f016020900481019282614a015760008555614935565b82601f10614a1a57805160ff1916838001178555614935565b82800160010185558215614935579182015b82811115614935578251825591602001919060010190614a2c565b508054614a5390615472565b6000825580601f10614a63575050565b601f01602090049060005260206000209081019061087491905b5b808211156111225760008155600101614a7e565b5b808211156111225780546001600160b01b0319168155600101614a93565b6001600160e01b03198116811461087457600080fd5b600060208284031215614ad957600080fd5b813561260181614ab1565b6001600160a01b038116811461087457600080fd5b600060208284031215614b0b57600080fd5b813561260181614ae4565b60005b83811015614b31578181015183820152602001614b19565b838111156111745750506000910152565b60008151808452614b5a816020860160208601614b16565b601f01601f19169290920160200192915050565b6020815260006126016020830184614b42565b600060208284031215614b9357600080fd5b5035919050565b6001600160a01b0391909116815260200190565b60008060408385031215614bc157600080fd5b8235614bcc81614ae4565b946020939093013593505050565b600081518084526020808501945080840160005b83811015614c0a57815187529582019590820190600101614bee565b509495945050505050565b6020815260006126016020830184614bda565b60008083601f840112614c3a57600080fd5b5081356001600160401b03811115614c5157600080fd5b602083019150836020828501011115610f3f57600080fd5b600080600060408486031215614c7e57600080fd5b8335925060208401356001600160401b03811115614c9b57600080fd5b614ca786828701614c28565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715614cec57614cec614cb4565b60405290565b604051601f8201601f191681016001600160401b0381118282101715614d1a57614d1a614cb4565b604052919050565b60006001600160401b03821115614d3b57614d3b614cb4565b5060051b60200190565b600082601f830112614d5657600080fd5b81356020614d6b614d6683614d22565b614cf2565b82815260059290921b84018101918181019086841115614d8a57600080fd5b8286015b84811015614da55780358352918301918301614d8e565b509695505050505050565b600060208284031215614dc257600080fd5b81356001600160401b03811115614dd857600080fd5b6129ee84828501614d45565b60008083601f840112614df657600080fd5b5081356001600160401b03811115614e0d57600080fd5b6020830191508360208260051b8501011115610f3f57600080fd5b600080600080600060608688031215614e4057600080fd5b8535945060208601356001600160401b0380821115614e5e57600080fd5b614e6a89838a01614de4565b90965094506040880135915080821115614e8357600080fd5b50614e9088828901614de4565b969995985093965092949392505050565b600080600060608486031215614eb657600080fd5b8335614ec181614ae4565b92506020840135614ed181614ae4565b929592945050506040919091013590565b60008060408385031215614ef557600080fd5b50508035926020909101359150565b6001600160a01b03929092168252602082015260400190565b60008060208385031215614f3057600080fd5b82356001600160401b03811115614f4657600080fd5b614f5285828601614c28565b90969095509350505050565b600080600060408486031215614f7357600080fd5b8335614f7e81614ae4565b925060208401356001600160401b03811115614c9b57600080fd5b6020808252825182820181905260009190848201906040850190845b81811015614fda5783516001600160a01b031683529284019291840191600101614fb5565b50909695505050505050565b60008060008060408587031215614ffc57600080fd5b84356001600160401b038082111561501357600080fd5b61501f88838901614de4565b9096509450602087013591508082111561503857600080fd5b5061504587828801614de4565b95989497509550505050565b60008060006040848603121561506657600080fd5b833561507181614ae4565b925060208401356001600160401b0381111561508c57600080fd5b614ca786828701614de4565b801515811461087457600080fd5b600080600080606085870312156150bc57600080fd5b84356150c781614ae4565b935060208501356001600160401b038111156150e257600080fd5b6150ee87828801614c28565b909450925050604085013561510281615098565b939692955090935050565b60008060006040848603121561512257600080fd5b83356001600160401b038082111561513957600080fd5b61514587838801614d45565b9450602086013591508082111561515b57600080fd5b50614ca786828701614de4565b60008060006040848603121561517d57600080fd5b83356001600160401b0381111561519357600080fd5b61519f86828701614c28565b90945092505060208401356151b381615098565b809150509250925092565b600080604083850312156151d157600080fd5b82356151dc81614ae4565b915060208301356151ec81615098565b809150509250929050565b60006020828403121561520957600080fd5b813561260181615098565b6000806040838503121561522757600080fd5b823561523281614ae4565b9150602083013561ffff811681146151ec57600080fd5b60008060008060006060868803121561526157600080fd5b853561526c81614ae4565b945060208601356001600160401b0380821115614e5e57600080fd5b60006001600160401b038211156152a1576152a1614cb4565b50601f01601f191660200190565b600080600080608085870312156152c557600080fd5b84356152d081614ae4565b935060208501356152e081614ae4565b92506040850135915060608501356001600160401b0381111561530257600080fd5b8501601f8101871361531357600080fd5b8035615321614d6682615288565b81815288602083850101111561533657600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600081518084526020808501945080840160005b83811015614c0a5781516001600160a01b03168752958201959082019060010161536c565b6020815260006126016020830184615358565b6040815260006153b76040830185615358565b82810360208401526153c98185614bda565b95945050505050565b6000806000606084860312156153e757600080fd5b833592506020840135915060408401356151b381614ae4565b6000806040838503121561541357600080fd5b823561541e81614ae4565b915060208301356151ec81614ae4565b60208082526024908201527f41646d696e436f6e74726f6c3a204d757374206265206f776e6572206f7220616040820152633236b4b760e11b606082015260800190565b600181811c9082168061548657607f821691505b602082108114156154a757634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252601190820152702737b732bc34b9ba32b73a103a37b5b2b760791b604082015260600190565b60208082526011908201527014195c9b5a5cdcda5bdb8819195b9a5959607a1b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60006000198214156155c8576155c861559e565b5060010190565b6000808335601e198436030181126155e657600080fd5b8301803591506001600160401b0382111561560057600080fd5b602001915036819003821315610f3f57600080fd5b6020808252600d908201526c125b9d985b1a59081a5b9c1d5d609a1b604082015260600190565b602080825260189082015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604082015260600190565b60008160001904831182151516156156885761568861559e565b500290565b60ff93841681529183166020830152909116604082015260600190565b600060208083850312156156bd57600080fd5b82516001600160401b03808211156156d457600080fd5b8185019150601f86818401126156e957600080fd5b6156f1614cca565b80604085018981111561570357600080fd5b855b818110156157935780518681111561571d5760008081fd5b87018581018c1361572e5760008081fd5b805161573c614d6682614d22565b81815260059190911b82018a01908a8101908e83111561575c5760008081fd5b928b01925b8284101561578357835161577481615098565b8252928b0192908b0190615761565b8752505050928701928701615705565b50909998505050505050505050565b634e487b7160e01b600052601260045260246000fd5b6000826157c7576157c76157a2565b500490565b6000826157db576157db6157a2565b500690565b7a19185d184e985c1c1b1a58d85d1a5bdb8bda9cdbdb8edd5d198e0b602a1b81526000835161581681601b850160208801614b16565b83519083019061582d81601b840160208801614b16565b61227d60f01b601b9290910191820152601d01949350505050565b6020808252600d908201526c24b73b30b634b2103a37b5b2b760991b604082015260600190565b6040808252810184905260008560608301825b878110156158b257823561589581614ae4565b6001600160a01b0316825260209283019290910190600101615882565b5083810360208501528481526001600160fb1b038511156158d257600080fd5b8460051b915081866020830137600091016020019081529695505050505050565b602080825260159082015274115e1d195b9cda5bdb88189b1858dadb1a5cdd1959605a1b604082015260600190565b6000828210156159345761593461559e565b500390565b6000821982111561594c5761594c61559e565b500190565b60008351615963818460208801614b16565b835190830190615977818360208801614b16565b01949350505050565b600060ff831680615993576159936157a2565b8060ff84160691505092915050565b8054600090600181811c90808316806159bc57607f831692505b60208084108214156159de57634e487b7160e01b600052602260045260246000fd5b838852602088018280156159f95760018114615a0a57615a35565b60ff19871682528282019750615a35565b60008981526020902060005b87811015615a2f57815484820152908601908401615a16565b83019850505b5050505050505092915050565b85815284602082015283604082015282606082015260c060808201526000615a6d60c08301846159a2565b82810360a084015260008152602081019150509695505050505050565b600060208284031215615a9c57600080fd5b81516001600160401b03811115615ab257600080fd5b8201601f81018413615ac357600080fd5b8051615ad1614d6682615288565b818152856020838501011115615ae657600080fd5b6153c9826020830160208601614b16565b85815284602082015283604082015282606082015260c060808201526000615b2260c08301846159a2565b82810360a084015260198152786d69782d626c656e642d6d6f64653a206d756c7469706c793b60381b6020820152604081019150509695505050505050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b600082601f830112615bc457600080fd5b81516020615bd4614d6683614d22565b82815260059290921b84018101918181019086841115615bf357600080fd5b8286015b84811015614da55780518352918301918301615bf7565b60008060408385031215615c2157600080fd5b82516001600160401b0380821115615c3857600080fd5b818501915085601f830112615c4c57600080fd5b81516020615c5c614d6683614d22565b82815260059290921b84018101918181019089841115615c7b57600080fd5b948201945b83861015615ca2578551615c9381614ae4565b82529482019490820190615c80565b91880151919650909350505080821115615cbb57600080fd5b50615cc885828601615bb3565b9150509250929050565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615d1b90830184614b42565b9695505050505050565b600060208284031215615d3757600080fd5b815161260181614ab1565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b600060208284031215615d7e57600080fd5b81516126018161509856fe222c20226465736372697074696f6e223a2246696775726520726570726573656e746174696f6e206f66203c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323030302f7376672720786d6c6e733a786c696e6b3d27687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b272069643d2766696775726573272077696474683d27d19cf84cf0fec6bec9ddfa29c63adf83a55707c712f32c8285d6180a789014792e222c2022637265617465645f6279223a2246696775726573222c202265787465726e616c5f75726c223a2268747470733a2f2f666967757265732e6172742f746f6b656e2fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef222c202261747472696275746573223a205b7b2274726169745f74797065223a20224e756d626572222c202276616c7565223a22a2646970667358221220059c573ac342175e96b4743f517ba47524e7a2434f5e14cc535ba1affa16386b64736f6c63430008090033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102eb5760003560e01c806301ffc9a7146102f057806302e7afb71461031857806306fdde031461032d578063081812fc14610342578063095ea7b3146103625780630ebd4c7f14610375578063162094c4146103955780631ebdc96a146103a857806320e4afe2146103bb57806322f374d0146103ce578063239be317146103df57806323b872dd146103f257806324d7806c146104055780632928ca58146104185780632a55205a146104395780632d3456701461045a57806330176e131461046d5780633071a0f91461048057806331ae450b14610493578063332dd1ae146104a857806338e52e78146104bb5780633e6134b8146104ce5780633f0f37f6146104e157806342842e0e146104f457806342966c6814610507578063596798ad1461051a57806361e5bc6b1461052d5780636352211e1461054057806366d1e9d0146105535780636d73e6691461056657806370a0823114610579578063715018a61461058c57806372ff03d3146105945780637884af44146105a75780637aa15f16146105ba57806382dcc0c8146105cd57806383b7db63146105e05780638c02cf30146105e85780638da5cb5b146105fb57806395d89b411461060357806399e0dd7c1461060b578063a22cb4651461061e578063aafb2d4414610631578063ac0c8cfa14610644578063ad2d0ddd14610657578063b0fe87c91461066a578063b88d4fde1461067d578063b98e631d14610690578063b9c4d9fb146106a3578063bb3bafd6146106c3578063c57380a2146106e4578063c87b56dd146106f5578063ce8aee9d14610708578063d5a06d4c146106c3578063ddbd273b1461071b578063e00aab4b14610740578063e7d3fe6b14610753578063e92a89f614610766578063e985e9c514610779578063f0cdc4991461078c578063f14210a61461079f578063f2fde38b146107b2578063f3d3d448146107c5578063fe2e1f58146107d8578063ffa1ad74146107eb575b600080fd5b6103036102fe366004614ac7565b6107f3565b60405190151581526020015b60405180910390f35b61032b610326366004614af9565b610822565b005b610335610877565b60405161030f9190614b6e565b610355610350366004614b81565b610909565b60405161030f9190614b9a565b61032b610370366004614bae565b610930565b610388610383366004614b81565b610a46565b60405161030f9190614c15565b61032b6103a3366004614c69565b610a76565b61032b6103b6366004614db0565b610ac1565b61032b6103c9366004614e28565b610daa565b600b546001600160a01b0316610355565b6103556103ed366004614b81565b610e23565b61032b610400366004614ea1565b610e53565b610303610413366004614af9565b610e84565b61042b610426366004614af9565b610eb3565b60405190815260200161030f565b61044c610447366004614ee2565b610f08565b60405161030f929190614f04565b61032b610468366004614af9565b610f46565b61032b61047b366004614f1d565b610fa3565b61032b61048e366004614f5e565b611022565b61049b611078565b60405161030f9190614f99565b61032b6104b6366004614fe6565b611126565b6103886104c9366004615051565b61117a565b61032b6104dc366004614f1d565b61128e565b61032b6104ef3660046150a6565b6112a2565b61032b610502366004614ea1565b6112f7565b61032b610515366004614b81565b611312565b61032b610528366004614af9565b6113b8565b61032b61053b36600461510d565b611401565b61035561054e366004614b81565b611483565b61032b610561366004614f1d565b6114b8565b61032b610574366004614af9565b6114ca565b61042b610587366004614af9565b611522565b61032b6115a8565b61042b6105a2366004614af9565b6115bc565b61042b6105b5366004614f5e565b61163f565b6103886105c8366004615051565b6116f5565b61032b6105db366004615168565b611835565b61049b611848565b6103356105f6366004614ee2565b6118e8565b610355611e9e565b610335611ead565b61032b610619366004614f1d565b611ebc565b61032b61062c3660046151be565b611f06565b61032b61063f36600461510d565b611f11565b61032b6106523660046151f7565b611fcb565b610388610665366004615214565b611fdd565b61032b610678366004615249565b6120ef565b61032b61068b3660046152af565b61213c565b601954610355906001600160a01b031681565b6106b66106b1366004614b81565b61216e565b60405161030f9190615391565b6106d66106d1366004614b81565b61219e565b60405161030f9291906153a4565b6019546001600160a01b0316610355565b610335610703366004614b81565b6121d8565b61032b610716366004614af9565b6121fc565b61072e610729366004614b81565b612245565b60405160ff909116815260200161030f565b61038861074e366004615214565b612271565b61032b6107613660046153d2565b612340565b61032b610774366004614c69565b612385565b610303610787366004615400565b612398565b61032b61079a366004615400565b6123c6565b61032b6107ad366004614b81565b612410565b61032b6107c0366004614af9565b612445565b61032b6107d3366004614af9565b6124bb565b61042b6107e6366004614f5e565b6124e5565b61042b600281565b60006107fe82612557565b8061080d575061080d8261257c565b8061081c575061081c826125b7565b92915050565b3361082b611e9e565b6001600160a01b0316148061084657506108466002336125ec565b61086b5760405162461bcd60e51b81526004016108629061542e565b60405180910390fd5b61087481612608565b50565b60606004805461088690615472565b80601f01602080910402602001604051908101604052809291908181526020018280546108b290615472565b80156108ff5780601f106108d4576101008083540402835291602001916108ff565b820191906000526020600020905b8154815290600101906020018083116108e257829003601f168201915b5050505050905090565b600061091482612702565b506000908152600860205260409020546001600160a01b031690565b600061093b82611483565b9050806001600160a01b0316836001600160a01b031614156109a95760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610862565b336001600160a01b03821614806109c557506109c58133612398565b610a375760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c00006064820152608401610862565b610a418383612727565b505050565b6060610a5182612795565b610a6d5760405162461bcd60e51b8152600401610862906154ad565b61081c826127b2565b33610a7f611e9e565b6001600160a01b03161480610a9a5750610a9a6002336125ec565b610ab65760405162461bcd60e51b81526004016108629061542e565b610a418383836127bd565b6019546001600160a01b03163314610aeb5760405162461bcd60e51b8152600401610862906154d8565b6040518060e00160405280610b1b606484600081518110610b0e57610b0e615503565b6020026020010151612825565b60ff1681526020016040518060800160405280610b46601486600181518110610b0e57610b0e615503565b60ff1660ff168152602001610b69601486600281518110610b0e57610b0e615503565b60ff1660ff168152602001610b8c601486600381518110610b0e57610b0e615503565b60ff1660ff168152602001610baf601486600481518110610b0e57610b0e615503565b60ff1660ff1681525081526020016040518060800160405280610be0601486600581518110610b0e57610b0e615503565b60ff1660ff168152602001610c03601486600681518110610b0e57610b0e615503565b60ff1660ff168152602001610c26601486600781518110610b0e57610b0e615503565b60ff1660ff168152602001610c49601486600881518110610b0e57610b0e615503565b60ff1660ff168152508152602001610c7061016884600981518110610b0e57610b0e615503565b60ff168152602001610c9161016884600a81518110610b0e57610b0e615503565b60ff168152602001610cb261016884600b81518110610b0e57610b0e615503565b60ff168152602001610cd361016884600c81518110610b0e57610b0e615503565b60ff168152506020600083600081518110610cf057610cf0615503565b6020908102919091018101518252818101929092526040016000208251815460ff191660ff90911617815590820151610d2f90600183019060046148b2565b506040820151610d4590600283019060046148b2565b50606082015160039091018054608084015160a085015160c09095015160ff90811663010000000263ff0000001996821662010000029690961663ffff0000199282166101000261ffff19909416919095161791909117169190911791909117905550565b33610db3611e9e565b6001600160a01b03161480610dce5750610dce6002336125ec565b610dea5760405162461bcd60e51b81526004016108629061542e565b610df385612795565b610e0f5760405162461bcd60e51b8152600401610862906154ad565b610e1c8585858585612885565b5050505050565b6000610e2e82612795565b610e4a5760405162461bcd60e51b8152600401610862906154ad565b61081c8261290c565b610e5d3382612997565b610e795760405162461bcd60e51b815260040161086290615519565b610a418383836129f6565b6000816001600160a01b0316610e98611e9e565b6001600160a01b0316148061081c575061081c6002836125ec565b600060026001541415610ed85760405162461bcd60e51b815260040161086290615567565b6002600155610ee5612b8b565b610efe8260405180602001604052806000815250612be1565b6001805592915050565b600080610f1484612795565b610f305760405162461bcd60e51b8152600401610862906154ad565b610f3a8484612c59565b915091505b9250929050565b610f4e612d2c565b610f596002826125ec565b156108745760405133906001600160a01b038316907f7c0c3c84c67c85fcac635147348bfe374c24a1a93d0366d1cfe9d8853cbf89d590600090a3610f9f600282612d8b565b5050565b33610fac611e9e565b6001600160a01b03161480610fc75750610fc76002336125ec565b610fe35760405162461bcd60e51b81526004016108629061542e565b610f9f82828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612da092505050565b3361102b611e9e565b6001600160a01b0316148061104657506110466002336125ec565b6110625760405162461bcd60e51b81526004016108629061542e565b61106b83612ddc565b610a418383836000612e04565b60606110846002612ef5565b6001600160401b0381111561109b5761109b614cb4565b6040519080825280602002602001820160405280156110c4578160200160208202803683370190505b50905060005b6110d46002612ef5565b811015611122576110e6600282612eff565b8282815181106110f8576110f8615503565b6001600160a01b03909216602092830291909101909101528061111a816155b4565b9150506110ca565b5090565b3361112f611e9e565b6001600160a01b0316148061114a575061114a6002336125ec565b6111665760405162461bcd60e51b81526004016108629061542e565b611174600085858585612f0b565b50505050565b60606002600154141561119f5760405162461bcd60e51b815260040161086290615567565b60026001556111ac612b8b565b816001600160401b038111156111c4576111c4614cb4565b6040519080825280602002602001820160405280156111ed578160200160208202803683370190505b50905060005b828110156112825761125d8585858481811061121157611211615503565b905060200281019061122391906155cf565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612be192505050565b82828151811061126f5761126f615503565b60209081029190910101526001016111f3565b50600180559392505050565b611296612b8b565b610f9f82826000612ff8565b336112ab611e9e565b6001600160a01b031614806112c657506112c66002336125ec565b6112e25760405162461bcd60e51b81526004016108629061542e565b6112eb84612ddc565b61117484848484612e04565b610a418383836040518060200160405280600081525061213c565b600260015414156113355760405162461bcd60e51b815260040161086290615567565b60026001556113443382612997565b6113905760405162461bcd60e51b815260206004820181905260248201527f43616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665646044820152606401610862565b600061139b82611483565b90506113a682613035565b6113b081836130ca565b505060018055565b336113c1611e9e565b6001600160a01b031614806113dc57506113dc6002336125ec565b6113f85760405162461bcd60e51b81526004016108629061542e565b610874816131dd565b611409612b8b565b825181146114295760405162461bcd60e51b815260040161086290615615565b60005b83518110156111745761147b84828151811061144a5761144a615503565b602002602001015184848481811061146457611464615503565b905060200281019061147691906155cf565b613233565b60010161142c565b6000818152600660205260408120546001600160a01b03168061081c5760405162461bcd60e51b81526004016108629061563c565b6114c0612b8b565b610f9f8282613269565b6114d2612d2c565b6114dd6002826125ec565b6108745760405133906001600160a01b038316907f7e1a1a08d52e4ba0e21554733d66165fd5151f99460116223d9e3a608eec5cb190600090a3610f9f600282613283565b60006001600160a01b03821661158c5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610862565b506001600160a01b031660009081526007602052604090205490565b6115b0612d2c565b6115ba6000613298565b565b6000600260015414156115e15760405162461bcd60e51b815260040161086290615567565b6002600155336115ef611e9e565b6001600160a01b0316148061160a575061160a6002336125ec565b6116265760405162461bcd60e51b81526004016108629061542e565b610efe82604051806020016040528060008152506132e8565b6000600260015414156116645760405162461bcd60e51b815260040161086290615567565b600260015533611672611e9e565b6001600160a01b0316148061168d575061168d6002336125ec565b6116a95760405162461bcd60e51b81526004016108629061542e565b6116e98484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506132e892505050565b60018055949350505050565b60606002600154141561171a5760405162461bcd60e51b815260040161086290615567565b600260015533611728611e9e565b6001600160a01b0316148061174357506117436002336125ec565b61175f5760405162461bcd60e51b81526004016108629061542e565b816001600160401b0381111561177757611777614cb4565b6040519080825280602002602001820160405280156117a0578160200160208202803683370190505b50905060005b8281101561128257611810858585848181106117c4576117c4615503565b90506020028101906117d691906155cf565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506132e892505050565b82828151811061182257611822615503565b60209081029190910101526001016117a6565b61183d612b8b565b610a41838383612ff8565b6060611854600c612ef5565b6001600160401b0381111561186b5761186b614cb4565b604051908082528060200260200182016040528015611894578160200160208202803683370190505b50905060005b6118a4600c612ef5565b811015611122576118b6600c82612eff565b8282815181106118c8576118c8615503565b6001600160a01b039092166020928302919091019091015260010161189a565b600082815260208080526040808320815160e081018352815460ff168152825160808101938490526060959486948594879493909284019160018401906004908288855b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161192c57505050928452505060408051608081019182905260209093019291506002840190600490826000855b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411611981575050509284525050506003919091015460ff80821660208085019190915261010083048216604080860191909152620100008404831660608601526301000000909304821660809094019390935283518251808401909352601883527719185d184e9a5b5859d94bdcdd99cade1b5b0edd5d198e0b60421b93830193909352919091169550909150611a4090849061330b565b9250611a64836040518060a0016040528060678152602001615db56067913961330b565b9250611a8683611a81601b54600a611a7c919061566e565b613337565b61330b565b9250611ab4836040518060400160405280600a81526020016927206865696768743d2760b01b81525061330b565b9250611acc83611a81601b54600a611a7c919061566e565b9250611af28360405180604001604052806002815260200161139f60f11b81525061330b565b9250611b0a83611a8183602001518460400151613434565b9250600a841015611bc8576060810151608082015160405163d92457e160e01b815260009273dfbdb7b2f45671bce9cce07a36b1f129f3ace0eb9263d92457e192611b5b928a92909160040161568d565b60006040518083038186803b158015611b7357600080fd5b505af4158015611b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611baf91908101906156aa565b9050611bc084611a81600084613712565b935050611d43565b6000611bd5600a866157b8565b90506000611be4600a876157cc565b9050600073119d6f3f921b774f46e06bd4656715e184d7c69a63fda13a3884866060015187608001516040518463ffffffff1660e01b8152600401611c2b9392919061568d565b60006040518083038186803b158015611c4357600080fd5b505af4158015611c57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c7f91908101906156aa565b9050600073119d6f3f921b774f46e06bd4656715e184d7c69a63fda13a38848760a001518860c001516040518463ffffffff1660e01b8152600401611cc69392919061568d565b60006040518083038186803b158015611cde57600080fd5b505af4158015611cf2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d1a91908101906156aa565b9050611d2b87611a81600085613712565b9650611d3c87611a81600184613712565b9650505050505b611d6b83604051806040016040528060068152602001651e17b9bb339f60d11b81525061330b565b9250611da3604051806040016040528060118152602001707b226e616d65223a22466967757265202360781b815250611a8188613337565b9150611dc7826040518060600160405280602b8152602001615d8a602b913961330b565b9150611dd682611a8186613337565b9150611dfa82604051806080016040528060468152602001615e3c6046913961330b565b9150611e0982611a8188613337565b9150611e2d82604051806060016040528060348152602001615ea26034913961330b565b9150611e3c82611a8186613337565b9150611e6e826040518060400160405280600e81526020016d113eae96101134b6b0b3b2911d1160911b81525061330b565b91508183604051602001611e839291906157e0565b60405160208183030381529060405294505050505092915050565b6000546001600160a01b031690565b60606005805461088690615472565b33611ec5611e9e565b6001600160a01b03161480611ee05750611ee06002336125ec565b611efc5760405162461bcd60e51b81526004016108629061542e565b610f9f82826138db565b610f9f33838361390f565b33611f1a611e9e565b6001600160a01b03161480611f355750611f356002336125ec565b611f515760405162461bcd60e51b81526004016108629061542e565b82518114611f715760405162461bcd60e51b815260040161086290615615565b60005b835181101561117457611fc3848281518110611f9257611f92615503565b6020026020010151848484818110611fac57611fac615503565b9050602002810190611fbe91906155cf565b6127bd565b600101611f74565b611fd3612b8b565b61087433826139da565b6060600260015414156120025760405162461bcd60e51b815260040161086290615567565b600260015533612010611e9e565b6001600160a01b0316148061202b575061202b6002336125ec565b6120475760405162461bcd60e51b81526004016108629061542e565b8161ffff166001600160401b0381111561206357612063614cb4565b60405190808252806020026020018201604052801561208c578160200160208202803683370190505b50905060005b8261ffff168161ffff1610156120e4576120bb84604051806020016040528060008152506132e8565b828261ffff16815181106120d1576120d1615503565b6020908102919091010152600101612092565b506001805592915050565b336120f8611e9e565b6001600160a01b0316148061211357506121136002336125ec565b61212f5760405162461bcd60e51b81526004016108629061542e565b610e1c8585858585612f0b565b6121463383612997565b6121625760405162461bcd60e51b815260040161086290615519565b61117484848484613a4f565b606061217982612795565b6121955760405162461bcd60e51b8152600401610862906154ad565b61081c82613a82565b6060806121aa83612795565b6121c65760405162461bcd60e51b8152600401610862906154ad565b6121cf83613a94565b91509150915091565b60606121e382612702565b6000828152601f602052604090205461081c90836118e8565b33612205611e9e565b6001600160a01b0316148061222057506122206002336125ec565b61223c5760405162461bcd60e51b81526004016108629061542e565b61087481613e51565b600061225082612702565b506000908152601f6020908152604080832054835290805290205460ff1690565b6060600260015414156122965760405162461bcd60e51b815260040161086290615567565b60026001556122a3612b8b565b8161ffff166001600160401b038111156122bf576122bf614cb4565b6040519080825280602002602001820160405280156122e8578160200160208202803683370190505b50905060005b8261ffff168161ffff1610156120e4576123178460405180602001604052806000815250612be1565b828261ffff168151811061232d5761232d615503565b60209081029190910101526001016122ee565b6019546001600160a01b0316331461236a5760405162461bcd60e51b8152600401610862906154d8565b6000838152601f60205260409020829055610a418184613e80565b61238d612b8b565b610a41838383613233565b6001600160a01b03918216600090815260096020908152604080832093909416825291909152205460ff1690565b336123cf611e9e565b6001600160a01b031614806123ea57506123ea6002336125ec565b6124065760405162461bcd60e51b81526004016108629061542e565b610f9f8282613fac565b612418612d2c565b604051339082156108fc029083906000818181858888f19350505050158015610f9f573d6000803e3d6000fd5b61244d612d2c565b6001600160a01b0381166124b25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610862565b61087481613298565b6124c3612d2c565b601980546001600160a01b0319166001600160a01b0392909216919091179055565b60006002600154141561250a5760405162461bcd60e51b815260040161086290615567565b6002600155612517612b8b565b6116e98484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612be192505050565b60006001600160e01b03198216639088c20760e01b148061081c575061081c826140e1565b60006001600160e01b031982166380ac58cd60e01b148061080d57506001600160e01b03198216635b5e139f60e01b148061081c575061081c825b60006001600160e01b03198216632a9f3abf60e11b148061081c57506301ffc9a760e01b6001600160e01b031983161461081c565b6000612601836001600160a01b038416614192565b9392505050565b6001600160a01b0381161580159061262957506001600160a01b0381163014155b6126715760405162461bcd60e51b815260206004820152601960248201527821b0b73737ba10313630b1b5b634b9ba103cb7bab939b2b63360391b6044820152606401610862565b61267c600c826125ec565b156126b25760405133906001600160a01b03831690600080516020615e1c83398151915290600090a36126b0600c82612d8b565b505b6126bd600e826125ec565b6108745760405133906001600160a01b038316907f05ac7bc5a606cd92a63365f9fda244499b9add0526b22d99937b6bd88181059c90600090a3610f9f600e82613283565b61270b81612795565b6108745760405162461bcd60e51b81526004016108629061563c565b600081815260086020526040902080546001600160a01b0319166001600160a01b038416908117909155819061275c82611483565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000908152600660205260409020546001600160a01b0316151590565b606061260182613a94565b6000831180156127cf5750600a548311155b80156127f057506000838152601260205260409020546001600160a01b0316155b61280c5760405162461bcd60e51b815260040161086290615848565b6000838152601660205260409020611174908383614941565b600082424433856040516020016128629493929190938452602084019290925260601b6001600160601b0319166040830152605482015260740190565b6040516020818303038152906040528051906020012060001c61260191906157cc565b612891848484846141aa565b60008581526018602052604081206128a8916149b5565b6128c784848484601860008b815260200190815260200160002061424f565b847fabb46fe0761d77584bde75697647804ffd8113abd4d8d06bc664150395eccdee858585856040516128fd949392919061586f565b60405180910390a25050505050565b6000818152601260205260409020546001600160a01b03168061296a5760405162461bcd60e51b815260206004820152601660248201527527379032bc3a32b739b4b7b7103337b9103a37b5b2b760511b6044820152606401610862565b612975600e826125ec565b156129925760405162461bcd60e51b8152600401610862906158f3565b919050565b6000806129a383611483565b9050806001600160a01b0316846001600160a01b031614806129ca57506129ca8185612398565b806129ee5750836001600160a01b03166129e384610909565b6001600160a01b0316145b949350505050565b826001600160a01b0316612a0982611483565b6001600160a01b031614612a6d5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610862565b6001600160a01b038216612acf5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610862565b612ada838383614312565b612ae5600082612727565b6001600160a01b0383166000908152600760205260408120805460019290612b0e908490615922565b90915550506001600160a01b0382166000908152600760205260408120805460019290612b3c908490615939565b909155505060008181526006602052604080822080546001600160a01b0319166001600160a01b038681169182179092559151849391871691600080516020615e8283398151915291a4505050565b612b96600c336125ec565b6115ba5760405162461bcd60e51b815260206004820152601c60248201527b26bab9ba103132903932b3b4b9ba32b932b21032bc3a32b739b4b7b760211b6044820152606401610862565b6000600a60008154612bf2906155b4565b9091555050600a54612c04838261431d565b600081815260126020526040902080546001600160a01b03191633179055612c2c83826143b1565b815115612c545760008181526016602090815260409091208351612c52928501906149d3565b505b61081c565b600080600080612c6886613a94565b91509150600182511115612cbd5760405162461bcd60e51b815260206004820152601c60248201527b26b7b932903a3430b71018903937bcb0b63a3c903932b1b2b4bb32b960211b6044820152606401610862565b8151612cd157306000935093505050610f3f565b81600081518110612ce457612ce4615503565b60200260200101516127108683600081518110612d0357612d03615503565b6020026020010151612d15919061566e565b612d1f91906157b8565b9350935050509250929050565b33612d35611e9e565b6001600160a01b0316146115ba5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610862565b6000612601836001600160a01b0384166143cb565b60008052601360209081528151610f9f917f8fa6efc3be94b5b348b21fea823fe8d100408cee9b7f90524494500445d8ff6c91908401906149d3565b612de7600e826125ec565b156108745760405162461bcd60e51b8152600401610862906158f3565b6001600160a01b0384163014801590612e2a5750612e2a846001600160a01b03166144be565b612e605760405162461bcd60e51b8152602060048201526007602482015266125b9d985b1a5960ca1b6044820152606401610862565b60405133906001600160a01b038616907fd8cb8ba4086944eabf43c5535b7712015e4d4c714b24bf812c040ea5b7a3e42a90600090a36001600160a01b0384166000908152601360205260409020612eb9908484614941565b506001600160a01b0384166000908152601460205260409020805460ff1916821515179055612ee9600c85613283565b506111748460016139da565b600061081c825490565b600061260183836144cd565b612f17848484846141aa565b6001600160a01b0385166000908152601760205260408120612f38916149b5565b612f6984848484601760008b6001600160a01b03166001600160a01b0316815260200190815260200160002061424f565b6001600160a01b038516612fb9577f2b6849d5976d799a5b0ca4dfd6b40a3d7afe9ea72c091fa01a958594f9a2659b84848484604051612fac949392919061586f565b60405180910390a1610e1c565b846001600160a01b03167f535a93d2cb000582c0ebeaa9be4890ec6a287f98eb2df00c54c300612fd78d8f858585856040516128fd949392919061586f565b336000908152601360205260409020613012908484614941565b50336000908152601460205260409020805460ff19169115159190911790555050565b600061304082611483565b905061304e81600084614312565b613059600083612727565b6001600160a01b0381166000908152600760205260408120805460019290613082908490615922565b909155505060008281526006602052604080822080546001600160a01b0319169055518391906001600160a01b03841690600080516020615e82833981519152908390a45050565b6000818152601260205260409020546001600160a01b03161561318757600081815260126020526040902054613110906001600160a01b03166311686e4b60e21b6144f7565b1561318757600081815260126020526040908190205490516311686e4b60e21b81526001600160a01b03909116906345a1b92c906131549085908590600401614f04565b600060405180830381600087803b15801561316e57600080fd5b505af1158015613182573d6000803e3d6000fd5b505050505b600081815260166020526040902080546131a090615472565b1590506131be5760008181526016602052604081206131be91614a47565b600090815260126020526040902080546001600160a01b031916905550565b600b80546001600160a01b0319166001600160a01b0383161790556040517f959c0e47a2fe3cf01e237ba4892e2cc3194d77cbfb33e434e40873225d6b595f90613228908390614b9a565b60405180910390a150565b6000838152601260205260409020546001600160a01b0316331461280c5760405162461bcd60e51b815260040161086290615848565b336000908152601560205260409020610a41908383614941565b6000612601836001600160a01b038416614513565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000600a600081546132f9906155b4565b9091555050600a54612c2c83826143b1565b60608282604051602001613320929190615951565b604051602081830303815290604052905092915050565b60608161335b5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613385578061336f816155b4565b915061337e9050600a836157b8565b915061335f565b6000816001600160401b0381111561339f5761339f614cb4565b6040519080825280601f01601f1916602001820160405280156133c9576020820181803683370190505b5090505b84156129ee576133de600183615922565b91506133eb600a866157cc565b6133f6906030615939565b60f81b81838151811061340b5761340b615503565b60200101906001600160f81b031916908160001a90535061342d600a866157b8565b94506133cd565b60408051602081019091526000808252606091905b600481101561370a576000600386836004811061346857613468615503565b60200201516134779190615980565b60ff1690506000600486846004811061349257613492615503565b60200201516134a19190615980565b60ff1690506134cb84604051806040016040528060038152602001621e339f60e91b81525061330b565b93506135d98473631dbcb629e85b5c5f2c23138596f212e5b6c460638d749263601b5460056002896134fd91906157cc565b613507919061566e565b613511919061566e565b601b54600561352160028b6157b8565b61352b919061566e565b613535919061566e565b601b5461354390600561566e565b601b5461355190600561566e565b601c8a6003811061356457613564615503565b016040518663ffffffff1660e01b8152600401613585959493929190615a42565b60006040518083038186803b15801561359d57600080fd5b505af41580156135b1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a819190810190615a8a565b935080600314156136135761360a84604051806040016040528060048152602001631e17b39f60e11b81525061330b565b935050506136f8565b6136cb8473631dbcb629e85b5c5f2c23138596f212e5b6c460638d749263601b54600560028961364391906157cc565b61364d919061566e565b613657919061566e565b601b54600561366760028b6157b8565b613671919061566e565b61367b919061566e565b601b5461368990600561566e565b601b5461369790600561566e565b601c89600381106136aa576136aa615503565b016040518663ffffffff1660e01b8152600401613585959493929190615af7565b93506136f384604051806040016040528060048152602001631e17b39f60e11b81525061330b565b935050505b80613702816155b4565b915050613449565b509392505050565b60606000831561372d57601b5461372a90600561566e565b90505b604080516020810190915260008082525b60028110156138d25760005b85826002811061375c5761375c615503565b6020020151518110156138bf576000600587846002811061377f5761377f615503565b60200201515161378f91906157b8565b90508683600281106137a3576137a3615503565b602002015182815181106137b9576137b9615503565b6020026020010151156137cc57506138af565b601b5480600087826137e160ff8716886157cc565b6137eb919061566e565b6137f59190615939565b9050600086600114156138105761380d83600561566e565b90505b8261381e60ff8716886157b8565b613828919061566e565b6138329082615939565b601b54604051635a696a6760e01b81526004810185905260248101839052604481019190915260806064820152600b60848201526a3235352c3132302c32313160a81b60a48201529091506138a790899073631dbcb629e85b5c5f2c23138596f212e5b6c46090635a696a679060c401613585565b975050505050505b6138b8816155b4565b905061374a565b50806138ca816155b4565b91505061373e565b50949350505050565b600080526015602052610a417fa31547ce6245cdb9ecea19cf8c7eb9f5974025bb4075011409251ae855b30aed8383614941565b816001600160a01b0316836001600160a01b0316141561396d5760405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b6044820152606401610862565b6001600160a01b03838116600081815260096020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6139eb826345ffcdad60e01b6144f7565b15610f9f576001600160a01b038216600081815260116020908152604091829020805460ff191685151590811790915591519182527f072a7592283e2c2d1d56d21517ff6013325e0f55483f4828373ff4d98b0a1a36910160405180910390a25050565b613a5a8484846129f6565b613a668484848461455d565b6111745760405162461bcd60e51b815260040161086290615b61565b6060613a8d82613a94565b5092915050565b606080600060186000858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015613b1657600084815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900461ffff1681830152825260019092019101613acc565b505050509050805160001415613c75576000848152601260205260409020546001600160a01b03168015613c7357613b5581634e53ee3d60e11b6144f7565b15613bef57604051634e53ee3d60e11b81526001600160a01b03821690639ca7dc7a90613b889030908990600401614f04565b60006040518083038186803b158015613ba057600080fd5b505afa158015613bb4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613bdc9190810190615c0e565b8151919550935015613bef575050915091565b6001600160a01b038116600090815260176020908152604080832080548251818502810185019093528083529193909284015b82821015613c6c57600084815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900461ffff1681830152825260019092019101613c22565b5050505091505b505b8051613d15576000808052601760209081527fd840e16649f6b9a295d95876f4633d3a6b10b55e8162971cf78afd886d5ec89b8054604080518285028101850190915281815293919290919084015b82821015613d0e57600084815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900461ffff1681830152825260019092019101613cc4565b5050505090505b805115613e4b5780516001600160401b03811115613d3557613d35614cb4565b604051908082528060200260200182016040528015613d5e578160200160208202803683370190505b50925080516001600160401b03811115613d7a57613d7a614cb4565b604051908082528060200260200182016040528015613da3578160200160208202803683370190505b50915060005b8151811015613e4957818181518110613dc457613dc4615503565b602002602001015160000151848281518110613de257613de2615503565b60200260200101906001600160a01b031690816001600160a01b031681525050818181518110613e1457613e14615503565b60200260200101516020015161ffff16838281518110613e3657613e36615503565b6020908102919091010152600101613da9565b505b50915091565b60405133906001600160a01b03831690600080516020615e1c83398151915290600090a3610f9f600c82612d8b565b6001600160a01b038216613ed65760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610862565b613edf81612795565b15613f2b5760405162461bcd60e51b815260206004820152601c60248201527b115490cdcc8c4e881d1bdad95b88185b1c9958591e481b5a5b9d195960221b6044820152606401610862565b613f3760008383614312565b6001600160a01b0382166000908152600760205260408120805460019290613f60908490615939565b909155505060008181526006602052604080822080546001600160a01b0319166001600160a01b0386169081179091559051839290600080516020615e82833981519152908290a45050565b613fb7600c836125ec565b6140035760405162461bcd60e51b815260206004820152601e60248201527f43726561746f72436f72653a20496e76616c696420657874656e73696f6e00006044820152606401610862565b6001600160a01b0381161580614025575061402581631e05385b60e31b6144f7565b6140635760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610862565b6001600160a01b03828116600090815260106020526040902054811690821614610f9f576001600160a01b0382811660008181526010602052604080822080546001600160a01b031916948616948517905551339392917f6a835c4fcf7e0d398db3762332fdaa1471814ad39f1e2d6d0b3fdabf8efee3e091a45050565b60006001600160e01b031982166314d9799760e21b148061411257506001600160e01b031982166328f10a2160e01b145b8061412157506141218261257c565b8061413c57506001600160e01b03198216635d9dd7eb60e11b145b8061415757506001600160e01b03198216632dde656160e21b145b8061417257506001600160e01b031982166335681b5360e21b145b8061081c57506001600160e01b0319821663152a902d60e11b1492915050565b60009081526001919091016020526040902054151590565b8281146141c95760405162461bcd60e51b815260040161086290615615565b6000805b82811015614203578383828181106141e7576141e7615503565b90506020020135826141f99190615939565b91506001016141cd565b506127108110610e1c5760405162461bcd60e51b8152602060048201526017602482015276496e76616c696420746f74616c20726f79616c7469657360481b6044820152606401610862565b60005b8281101561430a5781604051806040016040528088888581811061427857614278615503565b905060200201602081019061428d9190614af9565b6001600160a01b031681526020018686858181106142ad576142ad615503565b61ffff602091820293909301358316909352508354600181810186556000958652948390208451910180549490930151909116600160a01b026001600160b01b03199093166001600160a01b039091161791909117905501614252565b505050505050565b610a41838383614671565b336000908152601060205260409020546001600160a01b031615610f9f573360008181526010602052604090819020549051631e05385b60e31b815260048101929092526001600160a01b03848116602484015260448301849052169063f029c2d890606401600060405180830381600087803b15801561439d57600080fd5b505af115801561430a573d6000803e3d6000fd5b610f9f8282604051806020016040528060008152506147c3565b600081815260018301602052604081205480156144b45760006143ef600183615922565b855490915060009061440390600190615922565b905081811461446857600086600001828154811061442357614423615503565b906000526020600020015490508087600001848154811061444657614446615503565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061447957614479615cd2565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061081c565b600091505061081c565b6001600160a01b03163b151590565b60008260000182815481106144e4576144e4615503565b9060005260206000200154905092915050565b6000614502836147f6565b801561260157506126018383614829565b600061451f8383614192565b6145555750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561081c565b50600061081c565b6000614571846001600160a01b03166144be565b1561466657604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906145a8903390899088908890600401615ce8565b602060405180830381600087803b1580156145c257600080fd5b505af19250505080156145f2575060408051601f3d908101601f191682019092526145ef91810190615d25565b60015b61464c573d808015614620576040519150601f19603f3d011682016040523d82523d6000602084013e614625565b606091505b5080516146445760405162461bcd60e51b815260040161086290615b61565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506129ee565b506001949350505050565b6000818152601260209081526040808320546001600160a01b03168352601190915290205460ff161561477c5760008181526012602052604090819020549051632f3537c560e11b81526001600160a01b0390911690635e6a6f8a906146e1903390879087908790600401615d42565b602060405180830381600087803b1580156146fb57600080fd5b505af115801561470f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147339190615d6c565b610a415760405162461bcd60e51b815260206004820152601a602482015279457874656e73696f6e20617070726f76616c206661696c75726560301b6044820152606401610862565b600b546001600160a01b031615610a4157600b54604051632f3537c560e11b81526001600160a01b0390911690635e6a6f8a906146e1903390879087908790600401615d42565b6147cd8383613e80565b6147da600084848461455d565b610a415760405162461bcd60e51b815260040161086290615b61565b6000614809826301ffc9a760e01b614829565b801561081c5750614822826001600160e01b0319614829565b1592915050565b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b178152825160009392849283928392918391908a617530fa92503d9150600051905082801561489b575060208210155b80156148a75750600081115b979650505050505050565b6001830191839082156149355791602002820160005b8382111561490657835183826101000a81548160ff021916908360ff16021790555092602001926001016020816000010492830192600103026148c8565b80156149335782816101000a81549060ff0219169055600101602081600001049283019260010302614906565b505b50611122929150614a7d565b82805461494d90615472565b90600052602060002090601f01602090048101928261496f5760008555614935565b82601f106149885782800160ff19823516178555614935565b82800160010185558215614935579182015b8281111561493557823582559160200191906001019061499a565b50805460008255906000526020600020908101906108749190614a92565b8280546149df90615472565b90600052602060002090601f016020900481019282614a015760008555614935565b82601f10614a1a57805160ff1916838001178555614935565b82800160010185558215614935579182015b82811115614935578251825591602001919060010190614a2c565b508054614a5390615472565b6000825580601f10614a63575050565b601f01602090049060005260206000209081019061087491905b5b808211156111225760008155600101614a7e565b5b808211156111225780546001600160b01b0319168155600101614a93565b6001600160e01b03198116811461087457600080fd5b600060208284031215614ad957600080fd5b813561260181614ab1565b6001600160a01b038116811461087457600080fd5b600060208284031215614b0b57600080fd5b813561260181614ae4565b60005b83811015614b31578181015183820152602001614b19565b838111156111745750506000910152565b60008151808452614b5a816020860160208601614b16565b601f01601f19169290920160200192915050565b6020815260006126016020830184614b42565b600060208284031215614b9357600080fd5b5035919050565b6001600160a01b0391909116815260200190565b60008060408385031215614bc157600080fd5b8235614bcc81614ae4565b946020939093013593505050565b600081518084526020808501945080840160005b83811015614c0a57815187529582019590820190600101614bee565b509495945050505050565b6020815260006126016020830184614bda565b60008083601f840112614c3a57600080fd5b5081356001600160401b03811115614c5157600080fd5b602083019150836020828501011115610f3f57600080fd5b600080600060408486031215614c7e57600080fd5b8335925060208401356001600160401b03811115614c9b57600080fd5b614ca786828701614c28565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715614cec57614cec614cb4565b60405290565b604051601f8201601f191681016001600160401b0381118282101715614d1a57614d1a614cb4565b604052919050565b60006001600160401b03821115614d3b57614d3b614cb4565b5060051b60200190565b600082601f830112614d5657600080fd5b81356020614d6b614d6683614d22565b614cf2565b82815260059290921b84018101918181019086841115614d8a57600080fd5b8286015b84811015614da55780358352918301918301614d8e565b509695505050505050565b600060208284031215614dc257600080fd5b81356001600160401b03811115614dd857600080fd5b6129ee84828501614d45565b60008083601f840112614df657600080fd5b5081356001600160401b03811115614e0d57600080fd5b6020830191508360208260051b8501011115610f3f57600080fd5b600080600080600060608688031215614e4057600080fd5b8535945060208601356001600160401b0380821115614e5e57600080fd5b614e6a89838a01614de4565b90965094506040880135915080821115614e8357600080fd5b50614e9088828901614de4565b969995985093965092949392505050565b600080600060608486031215614eb657600080fd5b8335614ec181614ae4565b92506020840135614ed181614ae4565b929592945050506040919091013590565b60008060408385031215614ef557600080fd5b50508035926020909101359150565b6001600160a01b03929092168252602082015260400190565b60008060208385031215614f3057600080fd5b82356001600160401b03811115614f4657600080fd5b614f5285828601614c28565b90969095509350505050565b600080600060408486031215614f7357600080fd5b8335614f7e81614ae4565b925060208401356001600160401b03811115614c9b57600080fd5b6020808252825182820181905260009190848201906040850190845b81811015614fda5783516001600160a01b031683529284019291840191600101614fb5565b50909695505050505050565b60008060008060408587031215614ffc57600080fd5b84356001600160401b038082111561501357600080fd5b61501f88838901614de4565b9096509450602087013591508082111561503857600080fd5b5061504587828801614de4565b95989497509550505050565b60008060006040848603121561506657600080fd5b833561507181614ae4565b925060208401356001600160401b0381111561508c57600080fd5b614ca786828701614de4565b801515811461087457600080fd5b600080600080606085870312156150bc57600080fd5b84356150c781614ae4565b935060208501356001600160401b038111156150e257600080fd5b6150ee87828801614c28565b909450925050604085013561510281615098565b939692955090935050565b60008060006040848603121561512257600080fd5b83356001600160401b038082111561513957600080fd5b61514587838801614d45565b9450602086013591508082111561515b57600080fd5b50614ca786828701614de4565b60008060006040848603121561517d57600080fd5b83356001600160401b0381111561519357600080fd5b61519f86828701614c28565b90945092505060208401356151b381615098565b809150509250925092565b600080604083850312156151d157600080fd5b82356151dc81614ae4565b915060208301356151ec81615098565b809150509250929050565b60006020828403121561520957600080fd5b813561260181615098565b6000806040838503121561522757600080fd5b823561523281614ae4565b9150602083013561ffff811681146151ec57600080fd5b60008060008060006060868803121561526157600080fd5b853561526c81614ae4565b945060208601356001600160401b0380821115614e5e57600080fd5b60006001600160401b038211156152a1576152a1614cb4565b50601f01601f191660200190565b600080600080608085870312156152c557600080fd5b84356152d081614ae4565b935060208501356152e081614ae4565b92506040850135915060608501356001600160401b0381111561530257600080fd5b8501601f8101871361531357600080fd5b8035615321614d6682615288565b81815288602083850101111561533657600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600081518084526020808501945080840160005b83811015614c0a5781516001600160a01b03168752958201959082019060010161536c565b6020815260006126016020830184615358565b6040815260006153b76040830185615358565b82810360208401526153c98185614bda565b95945050505050565b6000806000606084860312156153e757600080fd5b833592506020840135915060408401356151b381614ae4565b6000806040838503121561541357600080fd5b823561541e81614ae4565b915060208301356151ec81614ae4565b60208082526024908201527f41646d696e436f6e74726f6c3a204d757374206265206f776e6572206f7220616040820152633236b4b760e11b606082015260800190565b600181811c9082168061548657607f821691505b602082108114156154a757634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252601190820152702737b732bc34b9ba32b73a103a37b5b2b760791b604082015260600190565b60208082526011908201527014195c9b5a5cdcda5bdb8819195b9a5959607a1b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60006000198214156155c8576155c861559e565b5060010190565b6000808335601e198436030181126155e657600080fd5b8301803591506001600160401b0382111561560057600080fd5b602001915036819003821315610f3f57600080fd5b6020808252600d908201526c125b9d985b1a59081a5b9c1d5d609a1b604082015260600190565b602080825260189082015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604082015260600190565b60008160001904831182151516156156885761568861559e565b500290565b60ff93841681529183166020830152909116604082015260600190565b600060208083850312156156bd57600080fd5b82516001600160401b03808211156156d457600080fd5b8185019150601f86818401126156e957600080fd5b6156f1614cca565b80604085018981111561570357600080fd5b855b818110156157935780518681111561571d5760008081fd5b87018581018c1361572e5760008081fd5b805161573c614d6682614d22565b81815260059190911b82018a01908a8101908e83111561575c5760008081fd5b928b01925b8284101561578357835161577481615098565b8252928b0192908b0190615761565b8752505050928701928701615705565b50909998505050505050505050565b634e487b7160e01b600052601260045260246000fd5b6000826157c7576157c76157a2565b500490565b6000826157db576157db6157a2565b500690565b7a19185d184e985c1c1b1a58d85d1a5bdb8bda9cdbdb8edd5d198e0b602a1b81526000835161581681601b850160208801614b16565b83519083019061582d81601b840160208801614b16565b61227d60f01b601b9290910191820152601d01949350505050565b6020808252600d908201526c24b73b30b634b2103a37b5b2b760991b604082015260600190565b6040808252810184905260008560608301825b878110156158b257823561589581614ae4565b6001600160a01b0316825260209283019290910190600101615882565b5083810360208501528481526001600160fb1b038511156158d257600080fd5b8460051b915081866020830137600091016020019081529695505050505050565b602080825260159082015274115e1d195b9cda5bdb88189b1858dadb1a5cdd1959605a1b604082015260600190565b6000828210156159345761593461559e565b500390565b6000821982111561594c5761594c61559e565b500190565b60008351615963818460208801614b16565b835190830190615977818360208801614b16565b01949350505050565b600060ff831680615993576159936157a2565b8060ff84160691505092915050565b8054600090600181811c90808316806159bc57607f831692505b60208084108214156159de57634e487b7160e01b600052602260045260246000fd5b838852602088018280156159f95760018114615a0a57615a35565b60ff19871682528282019750615a35565b60008981526020902060005b87811015615a2f57815484820152908601908401615a16565b83019850505b5050505050505092915050565b85815284602082015283604082015282606082015260c060808201526000615a6d60c08301846159a2565b82810360a084015260008152602081019150509695505050505050565b600060208284031215615a9c57600080fd5b81516001600160401b03811115615ab257600080fd5b8201601f81018413615ac357600080fd5b8051615ad1614d6682615288565b818152856020838501011115615ae657600080fd5b6153c9826020830160208601614b16565b85815284602082015283604082015282606082015260c060808201526000615b2260c08301846159a2565b82810360a084015260198152786d69782d626c656e642d6d6f64653a206d756c7469706c793b60381b6020820152604081019150509695505050505050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b600082601f830112615bc457600080fd5b81516020615bd4614d6683614d22565b82815260059290921b84018101918181019086841115615bf357600080fd5b8286015b84811015614da55780518352918301918301615bf7565b60008060408385031215615c2157600080fd5b82516001600160401b0380821115615c3857600080fd5b818501915085601f830112615c4c57600080fd5b81516020615c5c614d6683614d22565b82815260059290921b84018101918181019089841115615c7b57600080fd5b948201945b83861015615ca2578551615c9381614ae4565b82529482019490820190615c80565b91880151919650909350505080821115615cbb57600080fd5b50615cc885828601615bb3565b9150509250929050565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615d1b90830184614b42565b9695505050505050565b600060208284031215615d3757600080fd5b815161260181614ab1565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b600060208284031215615d7e57600080fd5b81516126018161509856fe222c20226465736372697074696f6e223a2246696775726520726570726573656e746174696f6e206f66203c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323030302f7376672720786d6c6e733a786c696e6b3d27687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b272069643d2766696775726573272077696474683d27d19cf84cf0fec6bec9ddfa29c63adf83a55707c712f32c8285d6180a789014792e222c2022637265617465645f6279223a2246696775726573222c202265787465726e616c5f75726c223a2268747470733a2f2f666967757265732e6172742f746f6b656e2fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef222c202261747472696275746573223a205b7b2274726169745f74797065223a20224e756d626572222c202276616c7565223a22a2646970667358221220059c573ac342175e96b4743f517ba47524e7a2434f5e14cc535ba1affa16386b64736f6c63430008090033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.