Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Transfer Ownersh... | 16097098 | 803 days ago | IN | 0 ETH | 0.0003633 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
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 Source Code Verified (Exact Match)
Contract Name:
NounsComposableDescriptor
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0 /// @title The Nouns Composable descriptor /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; import { Ownable } from '@openzeppelin/contracts/access/Ownable.sol'; import { Strings } from '@openzeppelin/contracts/utils/Strings.sol'; import { INounsComposableDescriptor } from './interfaces/INounsComposableDescriptor.sol'; import { INounsSeeder } from '../../interfaces/INounsSeeder.sol'; import { NFTDescriptorV2 } from '../../libs/NFTDescriptorV2.sol'; import { ISVGRenderer } from '../../interfaces/ISVGRenderer.sol'; import { INounsArt } from '../../interfaces/INounsArt.sol'; import { IInflator } from '../../interfaces/IInflator.sol'; import { INounsComposer } from './interfaces/INounsComposer.sol'; contract NounsComposableDescriptor is INounsComposableDescriptor, Ownable { using Strings for uint256; // prettier-ignore // https://creativecommons.org/publicdomain/zero/1.0/legalcode.txt bytes32 constant COPYRIGHT_CC0_1_0_UNIVERSAL_LICENSE = 0xa2010f343487d3f7618affe54f789f5487602331c0a8d03f49e9a7c547cf0499; /// @notice The contract responsible for holding compressed Noun art INounsArt public art; /// @notice The contract responsible for constructing SVGs ISVGRenderer public renderer; /// @notice The contract responsible for composability extension INounsComposer public composer; /// @notice Whether or not new Noun parts can be added bool public override arePartsLocked; /// @notice Whether or not `tokenURI` should be returned as a data URI (Default: true) bool public override isDataURIEnabled = true; /// @notice Base URI, used when isDataURIEnabled is false string public override baseURI; /** * @notice Require that the parts have not been locked. */ modifier whenPartsNotLocked() { require(!arePartsLocked, 'Parts are locked'); _; } constructor(INounsArt _art, ISVGRenderer _renderer, INounsComposer _composer) { art = _art; renderer = _renderer; composer = _composer; } /** * @notice Set the Noun's art contract. * @dev Only callable by the owner when not locked. */ function setArt(INounsArt _art) external onlyOwner whenPartsNotLocked { art = _art; emit ArtUpdated(_art); } /** * @notice Set the SVG renderer. * @dev Only callable by the owner. */ function setRenderer(ISVGRenderer _renderer) external onlyOwner { renderer = _renderer; emit RendererUpdated(_renderer); } /** * @notice Set the Composer. * @dev Only callable by the owner. */ function setComposer(INounsComposer _composer) external onlyOwner { composer = _composer; emit ComposerUpdated(_composer); } /** * @notice Set the art contract's `descriptor`. * @param descriptor the address to set. * @dev Only callable by the owner. */ function setArtDescriptor(address descriptor) external onlyOwner { art.setDescriptor(descriptor); } /** * @notice Set the art contract's `inflator`. * @param inflator the address to set. * @dev Only callable by the owner. */ function setArtInflator(IInflator inflator) external onlyOwner { art.setInflator(inflator); } /** * @notice Get the number of available Noun `backgrounds`. */ function backgroundCount() external view override returns (uint256) { return art.backgroundsCount(); } /** * @notice Get the number of available Noun `bodies`. */ function bodyCount() external view override returns (uint256) { return art.getBodiesTrait().storedImagesCount; } /** * @notice Get the number of available Noun `accessories`. */ function accessoryCount() external view override returns (uint256) { return art.getAccessoriesTrait().storedImagesCount; } /** * @notice Get the number of available Noun `heads`. */ function headCount() external view override returns (uint256) { return art.getHeadsTrait().storedImagesCount; } /** * @notice Get the number of available Noun `glasses`. */ function glassesCount() external view override returns (uint256) { return art.getGlassesTrait().storedImagesCount; } /** * @notice Batch add Noun backgrounds. * @dev This function can only be called by the owner when not locked. */ function addManyBackgrounds(string[] calldata _backgrounds) external override onlyOwner whenPartsNotLocked { art.addManyBackgrounds(_backgrounds); } /** * @notice Add a Noun background. * @dev This function can only be called by the owner when not locked. */ function addBackground(string calldata _background) external override onlyOwner whenPartsNotLocked { art.addBackground(_background); } /** * @notice Update a single color palette. This function can be used to * add a new color palette or update an existing palette. * @param paletteIndex the identifier of this palette * @param palette byte array of colors. every 3 bytes represent an RGB color. max length: 256 * 3 = 768 * @dev This function can only be called by the owner when not locked. */ function setPalette(uint8 paletteIndex, bytes calldata palette) external override onlyOwner whenPartsNotLocked { art.setPalette(paletteIndex, palette); } /** * @notice Add a batch of body images. * @param encodedCompressed bytes created by taking a string array of RLE-encoded images, abi encoding it as a bytes array, * and finally compressing it using deflate. * @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate. * @param imageCount the number of images in this batch; used when searching for images among batches. * @dev This function can only be called by the owner when not locked. */ function addBodies( bytes calldata encodedCompressed, uint80 decompressedLength, uint16 imageCount ) external override onlyOwner whenPartsNotLocked { art.addBodies(encodedCompressed, decompressedLength, imageCount); } /** * @notice Add a batch of accessory images. * @param encodedCompressed bytes created by taking a string array of RLE-encoded images, abi encoding it as a bytes array, * and finally compressing it using deflate. * @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate. * @param imageCount the number of images in this batch; used when searching for images among batches. * @dev This function can only be called by the owner when not locked. */ function addAccessories( bytes calldata encodedCompressed, uint80 decompressedLength, uint16 imageCount ) external override onlyOwner whenPartsNotLocked { art.addAccessories(encodedCompressed, decompressedLength, imageCount); } /** * @notice Add a batch of head images. * @param encodedCompressed bytes created by taking a string array of RLE-encoded images, abi encoding it as a bytes array, * and finally compressing it using deflate. * @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate. * @param imageCount the number of images in this batch; used when searching for images among batches. * @dev This function can only be called by the owner when not locked. */ function addHeads( bytes calldata encodedCompressed, uint80 decompressedLength, uint16 imageCount ) external override onlyOwner whenPartsNotLocked { art.addHeads(encodedCompressed, decompressedLength, imageCount); } /** * @notice Add a batch of glasses images. * @param encodedCompressed bytes created by taking a string array of RLE-encoded images, abi encoding it as a bytes array, * and finally compressing it using deflate. * @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate. * @param imageCount the number of images in this batch; used when searching for images among batches. * @dev This function can only be called by the owner when not locked. */ function addGlasses( bytes calldata encodedCompressed, uint80 decompressedLength, uint16 imageCount ) external override onlyOwner whenPartsNotLocked { art.addGlasses(encodedCompressed, decompressedLength, imageCount); } /** * @notice Update a single color palette. This function can be used to * add a new color palette or update an existing palette. This function does not check for data length validity * (len <= 768, len % 3 == 0). * @param paletteIndex the identifier of this palette * @param pointer the address of the contract holding the palette bytes. every 3 bytes represent an RGB color. * max length: 256 * 3 = 768. * @dev This function can only be called by the owner when not locked. */ function setPalettePointer(uint8 paletteIndex, address pointer) external override onlyOwner whenPartsNotLocked { art.setPalettePointer(paletteIndex, pointer); } /** * @notice Add a batch of body images from an existing storage contract. * @param pointer the address of a contract where the image batch was stored using SSTORE2. The data * format is expected to be like {encodedCompressed}: bytes created by taking a string array of * RLE-encoded images, abi encoding it as a bytes array, and finally compressing it using deflate. * @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate. * @param imageCount the number of images in this batch; used when searching for images among batches. * @dev This function can only be called by the owner when not locked. */ function addBodiesFromPointer( address pointer, uint80 decompressedLength, uint16 imageCount ) external override onlyOwner whenPartsNotLocked { art.addBodiesFromPointer(pointer, decompressedLength, imageCount); } /** * @notice Add a batch of accessory images from an existing storage contract. * @param pointer the address of a contract where the image batch was stored using SSTORE2. The data * format is expected to be like {encodedCompressed}: bytes created by taking a string array of * RLE-encoded images, abi encoding it as a bytes array, and finally compressing it using deflate. * @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate. * @param imageCount the number of images in this batch; used when searching for images among batches. * @dev This function can only be called by the owner when not locked. */ function addAccessoriesFromPointer( address pointer, uint80 decompressedLength, uint16 imageCount ) external override onlyOwner whenPartsNotLocked { art.addAccessoriesFromPointer(pointer, decompressedLength, imageCount); } /** * @notice Add a batch of head images from an existing storage contract. * @param pointer the address of a contract where the image batch was stored using SSTORE2. The data * format is expected to be like {encodedCompressed}: bytes created by taking a string array of * RLE-encoded images, abi encoding it as a bytes array, and finally compressing it using deflate. * @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate. * @param imageCount the number of images in this batch; used when searching for images among batches. * @dev This function can only be called by the owner when not locked. */ function addHeadsFromPointer( address pointer, uint80 decompressedLength, uint16 imageCount ) external override onlyOwner whenPartsNotLocked { art.addHeadsFromPointer(pointer, decompressedLength, imageCount); } /** * @notice Add a batch of glasses images from an existing storage contract. * @param pointer the address of a contract where the image batch was stored using SSTORE2. The data * format is expected to be like {encodedCompressed}: bytes created by taking a string array of * RLE-encoded images, abi encoding it as a bytes array, and finally compressing it using deflate. * @param decompressedLength the size in bytes the images bytes were prior to compression; required input for Inflate. * @param imageCount the number of images in this batch; used when searching for images among batches. * @dev This function can only be called by the owner when not locked. */ function addGlassesFromPointer( address pointer, uint80 decompressedLength, uint16 imageCount ) external override onlyOwner whenPartsNotLocked { art.addGlassesFromPointer(pointer, decompressedLength, imageCount); } /** * @notice Get a background color by ID. * @param index the index of the background. * @return string the RGB hex value of the background. */ function backgrounds(uint256 index) public view override returns (string memory) { return art.backgrounds(index); } /** * @notice Get a head image by ID. * @param index the index of the head. * @return bytes the RLE-encoded bytes of the image. */ function heads(uint256 index) public view override returns (bytes memory) { return art.heads(index); } /** * @notice Get a body image by ID. * @param index the index of the body. * @return bytes the RLE-encoded bytes of the image. */ function bodies(uint256 index) public view override returns (bytes memory) { return art.bodies(index); } /** * @notice Get an accessory image by ID. * @param index the index of the accessory. * @return bytes the RLE-encoded bytes of the image. */ function accessories(uint256 index) public view override returns (bytes memory) { return art.accessories(index); } /** * @notice Get a glasses image by ID. * @param index the index of the glasses. * @return bytes the RLE-encoded bytes of the image. */ function glasses(uint256 index) public view override returns (bytes memory) { return art.glasses(index); } /** * @notice Get a color palette by ID. * @param index the index of the palette. * @return bytes the palette bytes, where every 3 consecutive bytes represent a color in RGB format. */ function palettes(uint8 index) public view override returns (bytes memory) { return art.palettes(index); } /** * @notice Lock all Noun parts. * @dev This cannot be reversed and can only be called by the owner when not locked. */ function lockParts() external override onlyOwner whenPartsNotLocked { arePartsLocked = true; emit PartsLocked(); } /** * @notice Toggle a boolean value which determines if `tokenURI` returns a data URI * or an HTTP URL. * @dev This can only be called by the owner. */ function toggleDataURIEnabled() external override onlyOwner { bool enabled = !isDataURIEnabled; isDataURIEnabled = enabled; emit DataURIToggled(enabled); } /** * @notice Set the base URI for all token IDs. It is automatically * added as a prefix to the value returned in {tokenURI}, or to the * token ID if {tokenURI} is empty. * @dev This can only be called by the owner. */ function setBaseURI(string calldata _baseURI) external override onlyOwner { baseURI = _baseURI; emit BaseURIUpdated(_baseURI); } /** * @notice Given a token ID and seed, construct a token URI for an official Nouns DAO noun. * @dev The returned value may be a base64 encoded data URI or an API URL. */ function tokenURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view override returns (string memory) { if (isDataURIEnabled) { return dataURI(tokenId, seed); } return string(abi.encodePacked(baseURI, tokenId.toString())); } /** * @notice Given a token ID and seed, construct a base64 encoded data URI for an official Nouns DAO noun. */ function dataURI(uint256 tokenId, INounsSeeder.Seed memory seed) public view override returns (string memory) { string memory nounId = tokenId.toString(); string memory name = string(abi.encodePacked('CX Noun ', nounId)); string memory description = string(abi.encodePacked('CX Noun ', nounId, ' is a member of the Composables DAO')); return genericDataURI(name, description, tokenId, seed); } /** * @notice Given a name, description, tokenId and seed, construct a base64 encoded data URI. */ function genericDataURI( string memory name, string memory description, uint256 tokenId, INounsSeeder.Seed memory seed ) public view override returns (string memory) { NFTDescriptorV2.TokenURIParams memory params = NFTDescriptorV2.TokenURIParams({ name: name, description: description, parts: getPartsForSeed(tokenId, seed), background: art.backgrounds(seed.background) }); return NFTDescriptorV2.constructTokenURI(renderer, params); } /** * @notice Given a tokenId and seed, construct a base64 encoded SVG image. */ function generateSVGImage(uint256 tokenId, INounsSeeder.Seed memory seed) external view override returns (string memory) { ISVGRenderer.SVGParams memory params = ISVGRenderer.SVGParams({ parts: getPartsForSeed(tokenId, seed), background: art.backgrounds(seed.background) }); return NFTDescriptorV2.generateSVGImage(renderer, params); } /** * @notice Get all Noun parts for the passed tokenId and seed. */ function getPartsForSeed(uint256 tokenId, INounsSeeder.Seed memory seed) public view returns (ISVGRenderer.Part[] memory) { bytes memory body = art.bodies(seed.body); bytes memory accessory = art.accessories(seed.accessory); bytes memory head = art.heads(seed.head); bytes memory glasses_ = art.glasses(seed.glasses); ISVGRenderer.Part[] memory parts = new ISVGRenderer.Part[](4); parts[0] = ISVGRenderer.Part({ image: body, palette: _getPalette(body) }); parts[1] = ISVGRenderer.Part({ image: accessory, palette: _getPalette(accessory) }); parts[2] = ISVGRenderer.Part({ image: head, palette: _getPalette(head) }); parts[3] = ISVGRenderer.Part({ image: glasses_, palette: _getPalette(glasses_) }); //Get the composable parts ISVGRenderer.Part[] memory composableParts = composer.getParts(tokenId); uint256 len = composableParts.length; if (len < 12) { return parts; //fallback for misconfigured composers } //Merge the base parts and composable parts //Use the base parts if they have not been replaced if (composableParts[4].image.length == 0) { composableParts[4] = parts[0]; } if (composableParts[6].image.length == 0) { composableParts[6] = parts[1]; } if (composableParts[8].image.length == 0) { composableParts[8] = parts[2]; } if (composableParts[10].image.length == 0) { composableParts[10] = parts[3]; } //Count the number of non-empty spots uint256 mergedCount = 0; for (uint256 i = 0; i < len;) { if (composableParts[i].image.length > 0) { unchecked { mergedCount++; } } unchecked { i++; } } //Merge into resized array with no empty slots for renderer to handle uint256 mergedIndex = 0; ISVGRenderer.Part[] memory mergedParts = new ISVGRenderer.Part[](mergedCount); for (uint256 i = 0; i < len;) { if (composableParts[i].image.length > 0) { mergedParts[mergedIndex] = composableParts[i]; unchecked { mergedIndex++; } } unchecked { i++; } } return mergedParts; } /** * @notice Get the color palette pointer for the passed part. */ function _getPalette(bytes memory part) private view returns (bytes memory) { return art.palettes(uint8(part[0])); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.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 Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: GPL-3.0 /// @title Interface for Nouns Composable Descriptor /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; import { INounsSeeder } from '../../../interfaces/INounsSeeder.sol'; import { ISVGRenderer } from '../../../interfaces/ISVGRenderer.sol'; import { INounsArt } from '../../../interfaces/INounsArt.sol'; import { INounsDescriptorMinimal } from '../../../interfaces/INounsDescriptorMinimal.sol'; import { INounsComposer } from './INounsComposer.sol'; interface INounsComposableDescriptor is INounsDescriptorMinimal { event PartsLocked(); event DataURIToggled(bool enabled); event BaseURIUpdated(string baseURI); event ArtUpdated(INounsArt art); event RendererUpdated(ISVGRenderer renderer); event ComposerUpdated(INounsComposer renderer); error EmptyPalette(); error BadPaletteLength(); error IndexNotFound(); function arePartsLocked() external returns (bool); function isDataURIEnabled() external returns (bool); function baseURI() external returns (string memory); function palettes(uint8 paletteIndex) external view returns (bytes memory); function backgrounds(uint256 index) external view returns (string memory); function bodies(uint256 index) external view returns (bytes memory); function accessories(uint256 index) external view returns (bytes memory); function heads(uint256 index) external view returns (bytes memory); function glasses(uint256 index) external view returns (bytes memory); function backgroundCount() external view override returns (uint256); function bodyCount() external view override returns (uint256); function accessoryCount() external view override returns (uint256); function headCount() external view override returns (uint256); function glassesCount() external view override returns (uint256); function addManyBackgrounds(string[] calldata backgrounds) external; function addBackground(string calldata background) external; function setPalette(uint8 paletteIndex, bytes calldata palette) external; function addBodies( bytes calldata encodedCompressed, uint80 decompressedLength, uint16 imageCount ) external; function addAccessories( bytes calldata encodedCompressed, uint80 decompressedLength, uint16 imageCount ) external; function addHeads( bytes calldata encodedCompressed, uint80 decompressedLength, uint16 imageCount ) external; function addGlasses( bytes calldata encodedCompressed, uint80 decompressedLength, uint16 imageCount ) external; function setPalettePointer(uint8 paletteIndex, address pointer) external; function addBodiesFromPointer( address pointer, uint80 decompressedLength, uint16 imageCount ) external; function addAccessoriesFromPointer( address pointer, uint80 decompressedLength, uint16 imageCount ) external; function addHeadsFromPointer( address pointer, uint80 decompressedLength, uint16 imageCount ) external; function addGlassesFromPointer( address pointer, uint80 decompressedLength, uint16 imageCount ) external; function lockParts() external; function toggleDataURIEnabled() external; function setBaseURI(string calldata baseURI) external; function tokenURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view override returns (string memory); function dataURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view override returns (string memory); function genericDataURI( string calldata name, string calldata description, uint256 tokenId, INounsSeeder.Seed memory seed ) external view returns (string memory); function generateSVGImage(uint256 tokenId, INounsSeeder.Seed memory seed) external view returns (string memory); }
// SPDX-License-Identifier: GPL-3.0 /// @title Interface for NounsSeeder /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; import { INounsDescriptorMinimal } from './INounsDescriptorMinimal.sol'; interface INounsSeeder { struct Seed { uint48 background; uint48 body; uint48 accessory; uint48 head; uint48 glasses; } function generateSeed(uint256 nounId, INounsDescriptorMinimal descriptor) external view returns (Seed memory); }
// SPDX-License-Identifier: GPL-3.0 /// @title A library used to construct ERC721 token URIs and SVG images /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; import { Base64 } from 'base64-sol/base64.sol'; import { ISVGRenderer } from '../interfaces/ISVGRenderer.sol'; library NFTDescriptorV2 { struct TokenURIParams { string name; string description; string background; ISVGRenderer.Part[] parts; } /** * @notice Construct an ERC721 token URI. */ function constructTokenURI(ISVGRenderer renderer, TokenURIParams memory params) public view returns (string memory) { string memory image = generateSVGImage( renderer, ISVGRenderer.SVGParams({ parts: params.parts, background: params.background }) ); // prettier-ignore return string( abi.encodePacked( 'data:application/json;base64,', Base64.encode( bytes( abi.encodePacked('{"name":"', params.name, '", "description":"', params.description, '", "image": "', 'data:image/svg+xml;base64,', image, '"}') ) ) ) ); } /** * @notice Generate an SVG image for use in the ERC721 token URI. */ function generateSVGImage(ISVGRenderer renderer, ISVGRenderer.SVGParams memory params) public view returns (string memory svg) { return Base64.encode(bytes(renderer.generateSVG(params))); } }
// SPDX-License-Identifier: GPL-3.0 /// @title Interface for SVGRenderer /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; interface ISVGRenderer { struct Part { bytes image; bytes palette; } struct SVGParams { Part[] parts; string background; } function generateSVG(SVGParams memory params) external view returns (string memory svg); function generateSVGPart(Part memory part) external view returns (string memory partialSVG); function generateSVGParts(Part[] memory parts) external view returns (string memory partialSVG); }
// SPDX-License-Identifier: GPL-3.0 /// @title Interface for NounsArt /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; import { Inflate } from '../libs/Inflate.sol'; import { IInflator } from './IInflator.sol'; interface INounsArt { error SenderIsNotDescriptor(); error EmptyPalette(); error BadPaletteLength(); error EmptyBytes(); error BadDecompressedLength(); error BadImageCount(); error ImageNotFound(); error PaletteNotFound(); event DescriptorUpdated(address oldDescriptor, address newDescriptor); event InflatorUpdated(address oldInflator, address newInflator); event BackgroundsAdded(uint256 count); event PaletteSet(uint8 paletteIndex); event BodiesAdded(uint16 count); event AccessoriesAdded(uint16 count); event HeadsAdded(uint16 count); event GlassesAdded(uint16 count); struct NounArtStoragePage { uint16 imageCount; uint80 decompressedLength; address pointer; } struct Trait { NounArtStoragePage[] storagePages; uint256 storedImagesCount; } function descriptor() external view returns (address); function inflator() external view returns (IInflator); function setDescriptor(address descriptor) external; function setInflator(IInflator inflator) external; function addManyBackgrounds(string[] calldata _backgrounds) external; function addBackground(string calldata _background) external; function palettes(uint8 paletteIndex) external view returns (bytes memory); function setPalette(uint8 paletteIndex, bytes calldata palette) external; function addBodies( bytes calldata encodedCompressed, uint80 decompressedLength, uint16 imageCount ) external; function addAccessories( bytes calldata encodedCompressed, uint80 decompressedLength, uint16 imageCount ) external; function addHeads( bytes calldata encodedCompressed, uint80 decompressedLength, uint16 imageCount ) external; function addGlasses( bytes calldata encodedCompressed, uint80 decompressedLength, uint16 imageCount ) external; function addBodiesFromPointer( address pointer, uint80 decompressedLength, uint16 imageCount ) external; function setPalettePointer(uint8 paletteIndex, address pointer) external; function addAccessoriesFromPointer( address pointer, uint80 decompressedLength, uint16 imageCount ) external; function addHeadsFromPointer( address pointer, uint80 decompressedLength, uint16 imageCount ) external; function addGlassesFromPointer( address pointer, uint80 decompressedLength, uint16 imageCount ) external; function backgroundsCount() external view returns (uint256); function backgrounds(uint256 index) external view returns (string memory); function heads(uint256 index) external view returns (bytes memory); function bodies(uint256 index) external view returns (bytes memory); function accessories(uint256 index) external view returns (bytes memory); function glasses(uint256 index) external view returns (bytes memory); function getBodiesTrait() external view returns (Trait memory); function getAccessoriesTrait() external view returns (Trait memory); function getHeadsTrait() external view returns (Trait memory); function getGlassesTrait() external view returns (Trait memory); }
// SPDX-License-Identifier: GPL-3.0 /// @title Interface for Inflator /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; import { Inflate } from '../libs/Inflate.sol'; interface IInflator { function puff(bytes memory source, uint256 destlen) external pure returns (Inflate.ErrorCode, bytes memory); }
// SPDX-License-Identifier: GPL-3.0 /// @title Interface for Nouns Composer /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; import { ISVGRenderer } from '../../../interfaces/ISVGRenderer.sol'; interface INounsComposer { struct ChildToken { address tokenAddress; uint256 tokenId; } struct ChildTokenState { uint256 balance; uint64 index; uint16 position1; //position is a 1-based index uint8 boundTop1; //top is a 1-based index uint8 boundLeft1; //left is a 1-based index } struct TokenTransferParams { address tokenAddress; uint256 tokenId; uint256 amount; } struct TokenPositionParams { address tokenAddress; uint256 tokenId; uint16 position1; //position is a 1-based index uint8 boundTop1; //top is a 1-based index uint8 boundLeft1; //left is a 1-based index } struct TokenFullParams { address tokenAddress; uint256 tokenId; uint256 amount; uint16 position1; //position is a 1-based index uint8 boundTop1; //top is a 1-based index uint8 boundLeft1; //left is a 1-based index } event ChildReceived(uint256 indexed tokenId, address indexed from, address indexed childTokenAddress, uint256 childTokenId, uint256 amount); event ChildTransferred(uint256 indexed tokenId, address indexed to, address indexed childTokenAddress, uint256 childTokenId, uint256 amount); event CompositionAdded(uint256 indexed tokenId, address indexed childTokenAddress, uint256 indexed childTokenId, uint16 position1, uint8 boundTop1, uint8 boundLeft1); event CompositionRemoved(uint256 indexed tokenId, address indexed childTokenAddress, uint256 indexed childTokenId, uint16 position1); function getChildContracts(uint256 _tokenId) external view returns (address[] memory); function getChildTokens(uint256 _tokenId, address _childTokenAddress) external view returns (uint256[] memory); function getChildContractCount(uint256 _tokenId) external view returns (uint256); function getChildTokenCount(uint256 _tokenId, address _childTokenAddress) external view returns (uint256); function getChildTokenState(uint256 _tokenId, address _childTokenAddress, uint256 _childTokenId) external view returns (ChildTokenState memory); function getChildTokenStateBatch(uint256 _tokenId, address[] calldata _childTokenAddresses, uint256[] calldata _childTokenIds) external view returns (ChildTokenState[] memory); function getComposedChild(uint256 tokenId, uint16 position1) external view returns (ChildToken memory); function getComposedChildBatch(uint256 _tokenId, uint16 _position1Start, uint16 _position1End) external view returns (ChildToken[] memory); function childExists(uint256 _tokenId, address _childTokenAddress, uint256 _childTokenId) external view returns (bool); function receiveChild(uint256 _tokenId, TokenTransferParams calldata _child) external; function receiveChildBatch(uint256 _tokenId, TokenTransferParams[] calldata _children) external; function receiveAndComposeChild(uint256 _tokenId, TokenFullParams calldata _child) external; function receiveAndComposeChildBatch(uint256 _tokenId, TokenFullParams[] calldata _children) external; function receiveAndComposeChildBatchMixed(uint256 _tokenId, TokenTransferParams[] calldata _childrenReceive, TokenPositionParams[] calldata _childrenCompose) external; function transferChild(uint256 _tokenId, address _to, TokenTransferParams calldata _child) external; function transferChildBatch(uint256 _tokenId, address _to, TokenTransferParams[] calldata _children) external; function composeChild(uint256 _tokenId, TokenPositionParams calldata _child) external; function composeChildBatch(uint256 _tokenId, TokenPositionParams[] calldata _children) external; function removeComposedChild(uint256 _tokenId, uint16 _position1) external; function removeComposedChildBatch(uint256 _tokenId, uint16[] calldata _position1s) external; function getParts(uint256 _tokenId) external view returns (ISVGRenderer.Part[] memory); function hasParts(uint256 _tokenId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (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: GPL-3.0 /// @title Common interface for NounsDescriptor versions, as used by NounsToken and NounsSeeder. /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; import { INounsSeeder } from './INounsSeeder.sol'; interface INounsDescriptorMinimal { /// /// USED BY TOKEN /// function tokenURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view returns (string memory); function dataURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view returns (string memory); /// /// USED BY SEEDER /// function backgroundCount() external view returns (uint256); function bodyCount() external view returns (uint256); function accessoryCount() external view returns (uint256); function headCount() external view returns (uint256); function glassesCount() external view returns (uint256); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity >=0.8.0 <0.9.0; /// @notice Based on https://github.com/madler/zlib/blob/master/contrib/puff /// @dev Modified the original code for gas optimizations /// 1. Disable overflow/underflow checks /// 2. Chunk some loop iterations library Inflate { // Maximum bits in a code uint256 constant MAXBITS = 15; // Maximum number of literal/length codes uint256 constant MAXLCODES = 286; // Maximum number of distance codes uint256 constant MAXDCODES = 30; // Maximum codes lengths to read uint256 constant MAXCODES = (MAXLCODES + MAXDCODES); // Number of fixed literal/length codes uint256 constant FIXLCODES = 288; // Error codes enum ErrorCode { ERR_NONE, // 0 successful inflate ERR_NOT_TERMINATED, // 1 available inflate data did not terminate ERR_OUTPUT_EXHAUSTED, // 2 output space exhausted before completing inflate ERR_INVALID_BLOCK_TYPE, // 3 invalid block type (type == 3) ERR_STORED_LENGTH_NO_MATCH, // 4 stored block length did not match one's complement ERR_TOO_MANY_LENGTH_OR_DISTANCE_CODES, // 5 dynamic block code description: too many length or distance codes ERR_CODE_LENGTHS_CODES_INCOMPLETE, // 6 dynamic block code description: code lengths codes incomplete ERR_REPEAT_NO_FIRST_LENGTH, // 7 dynamic block code description: repeat lengths with no first length ERR_REPEAT_MORE, // 8 dynamic block code description: repeat more than specified lengths ERR_INVALID_LITERAL_LENGTH_CODE_LENGTHS, // 9 dynamic block code description: invalid literal/length code lengths ERR_INVALID_DISTANCE_CODE_LENGTHS, // 10 dynamic block code description: invalid distance code lengths ERR_MISSING_END_OF_BLOCK, // 11 dynamic block code description: missing end-of-block code ERR_INVALID_LENGTH_OR_DISTANCE_CODE, // 12 invalid literal/length or distance code in fixed or dynamic block ERR_DISTANCE_TOO_FAR, // 13 distance is too far back in fixed or dynamic block ERR_CONSTRUCT // 14 internal: error in construct() } // Input and output state struct State { ////////////////// // Output state // ////////////////// // Output buffer bytes output; // Bytes written to out so far uint256 outcnt; ///////////////// // Input state // ///////////////// // Input buffer bytes input; // Bytes read so far uint256 incnt; //////////////// // Temp state // //////////////// // Bit buffer uint256 bitbuf; // Number of bits in bit buffer uint256 bitcnt; ////////////////////////// // Static Huffman codes // ////////////////////////// Huffman lencode; Huffman distcode; } // Huffman code decoding tables struct Huffman { uint256[] counts; uint256[] symbols; } function bits(State memory s, uint256 need) private pure returns (ErrorCode, uint256) { unchecked { // Bit accumulator (can use up to 20 bits) uint256 val; // Load at least need bits into val val = s.bitbuf; while (s.bitcnt < need) { if (s.incnt == s.input.length) { // Out of input return (ErrorCode.ERR_NOT_TERMINATED, 0); } // Load eight bits val |= uint256(uint8(s.input[s.incnt++])) << s.bitcnt; s.bitcnt += 8; } // Drop need bits and update buffer, always zero to seven bits left s.bitbuf = val >> need; s.bitcnt -= need; // Return need bits, zeroing the bits above that uint256 ret = (val & ((1 << need) - 1)); return (ErrorCode.ERR_NONE, ret); } } function _stored(State memory s) private pure returns (ErrorCode) { unchecked { // Length of stored block uint256 len; // Discard leftover bits from current byte (assumes s.bitcnt < 8) s.bitbuf = 0; s.bitcnt = 0; // Get length and check against its one's complement if (s.incnt + 4 > s.input.length) { // Not enough input return ErrorCode.ERR_NOT_TERMINATED; } len = uint256(uint8(s.input[s.incnt++])); len |= uint256(uint8(s.input[s.incnt++])) << 8; if (uint8(s.input[s.incnt++]) != (~len & 0xFF) || uint8(s.input[s.incnt++]) != ((~len >> 8) & 0xFF)) { // Didn't match complement! return ErrorCode.ERR_STORED_LENGTH_NO_MATCH; } // Copy len bytes from in to out if (s.incnt + len > s.input.length) { // Not enough input return ErrorCode.ERR_NOT_TERMINATED; } if (s.outcnt + len > s.output.length) { // Not enough output space return ErrorCode.ERR_OUTPUT_EXHAUSTED; } while (len != 0) { // Note: Solidity reverts on underflow, so we decrement here len -= 1; s.output[s.outcnt++] = s.input[s.incnt++]; } // Done with a valid stored block return ErrorCode.ERR_NONE; } } function _decode(State memory s, Huffman memory h) private pure returns (ErrorCode, uint256) { unchecked { // Current number of bits in code uint256 len; // Len bits being decoded uint256 code = 0; // First code of length len uint256 first = 0; // Number of codes of length len uint256 count; // Index of first code of length len in symbol table uint256 index = 0; // Error code ErrorCode err; uint256 tempCode; for (len = 1; len <= MAXBITS; len += 5) { // Get next bit (err, tempCode) = bits(s, 1); if (err != ErrorCode.ERR_NONE) { return (err, 0); } code |= tempCode; count = h.counts[len]; // If length len, return symbol if (code < first + count) { return (ErrorCode.ERR_NONE, h.symbols[index + (code - first)]); } // Else update for next length index += count; first += count; first <<= 1; code <<= 1; // Get next bit (err, tempCode) = bits(s, 1); if (err != ErrorCode.ERR_NONE) { return (err, 0); } code |= tempCode; count = h.counts[len + 1]; // If length len, return symbol if (code < first + count) { return (ErrorCode.ERR_NONE, h.symbols[index + (code - first)]); } // Else update for next length index += count; first += count; first <<= 1; code <<= 1; // Get next bit (err, tempCode) = bits(s, 1); if (err != ErrorCode.ERR_NONE) { return (err, 0); } code |= tempCode; count = h.counts[len + 2]; // If length len, return symbol if (code < first + count) { return (ErrorCode.ERR_NONE, h.symbols[index + (code - first)]); } // Else update for next length index += count; first += count; first <<= 1; code <<= 1; // Get next bit (err, tempCode) = bits(s, 1); if (err != ErrorCode.ERR_NONE) { return (err, 0); } code |= tempCode; count = h.counts[len + 3]; // If length len, return symbol if (code < first + count) { return (ErrorCode.ERR_NONE, h.symbols[index + (code - first)]); } // Else update for next length index += count; first += count; first <<= 1; code <<= 1; // Get next bit (err, tempCode) = bits(s, 1); if (err != ErrorCode.ERR_NONE) { return (err, 0); } code |= tempCode; count = h.counts[len + 4]; // If length len, return symbol if (code < first + count) { return (ErrorCode.ERR_NONE, h.symbols[index + (code - first)]); } // Else update for next length index += count; first += count; first <<= 1; code <<= 1; } // Ran out of codes return (ErrorCode.ERR_INVALID_LENGTH_OR_DISTANCE_CODE, 0); } } function _construct( Huffman memory h, uint256[] memory lengths, uint256 n, uint256 start ) private pure returns (ErrorCode) { unchecked { // Current symbol when stepping through lengths[] uint256 symbol; // Current length when stepping through h.counts[] uint256 len; // Number of possible codes left of current length uint256 left; // Offsets in symbol table for each length uint256[MAXBITS + 1] memory offs; // Count number of codes of each length for (len = 0; len <= MAXBITS; ++len) { h.counts[len] = 0; } for (symbol = 0; symbol < n; ++symbol) { // Assumes lengths are within bounds ++h.counts[lengths[start + symbol]]; } // No codes! if (h.counts[0] == n) { // Complete, but decode() will fail return (ErrorCode.ERR_NONE); } // Check for an over-subscribed or incomplete set of lengths // One possible code of zero length left = 1; for (len = 1; len <= MAXBITS; len += 5) { // One more bit, double codes left left <<= 1; if (left < h.counts[len]) { // Over-subscribed--return error return ErrorCode.ERR_CONSTRUCT; } // Deduct count from possible codes left -= h.counts[len]; // One more bit, double codes left left <<= 1; if (left < h.counts[len + 1]) { // Over-subscribed--return error return ErrorCode.ERR_CONSTRUCT; } // Deduct count from possible codes left -= h.counts[len + 1]; // One more bit, double codes left left <<= 1; if (left < h.counts[len + 2]) { // Over-subscribed--return error return ErrorCode.ERR_CONSTRUCT; } // Deduct count from possible codes left -= h.counts[len + 2]; // One more bit, double codes left left <<= 1; if (left < h.counts[len + 3]) { // Over-subscribed--return error return ErrorCode.ERR_CONSTRUCT; } // Deduct count from possible codes left -= h.counts[len + 3]; // One more bit, double codes left left <<= 1; if (left < h.counts[len + 4]) { // Over-subscribed--return error return ErrorCode.ERR_CONSTRUCT; } // Deduct count from possible codes left -= h.counts[len + 4]; } // Generate offsets into symbol table for each length for sorting offs[1] = 0; for (len = 1; len < MAXBITS; ++len) { offs[len + 1] = offs[len] + h.counts[len]; } // Put symbols in table sorted by length, by symbol order within each length for (symbol = 0; symbol < n; ++symbol) { if (lengths[start + symbol] != 0) { h.symbols[offs[lengths[start + symbol]]++] = symbol; } } // Left > 0 means incomplete return left > 0 ? ErrorCode.ERR_CONSTRUCT : ErrorCode.ERR_NONE; } } function _codes( State memory s, Huffman memory lencode, Huffman memory distcode ) private pure returns (ErrorCode) { unchecked { // Decoded symbol uint256 symbol; // Length for copy uint256 len; // Distance for copy uint256 dist; // TODO Solidity doesn't support constant arrays, but these are fixed at compile-time // Size base for length codes 257..285 uint16[29] memory lens = [ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 ]; // Extra bits for length codes 257..285 uint8[29] memory lext = [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 ]; // Offset base for distance codes 0..29 uint16[30] memory dists = [ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 ]; // Extra bits for distance codes 0..29 uint8[30] memory dext = [ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 ]; // Error code ErrorCode err; // Decode literals and length/distance pairs while (symbol != 256) { (err, symbol) = _decode(s, lencode); if (err != ErrorCode.ERR_NONE) { // Invalid symbol return err; } if (symbol < 256) { // Literal: symbol is the byte // Write out the literal if (s.outcnt == s.output.length) { return ErrorCode.ERR_OUTPUT_EXHAUSTED; } s.output[s.outcnt] = bytes1(uint8(symbol)); ++s.outcnt; } else if (symbol > 256) { uint256 tempBits; // Length // Get and compute length symbol -= 257; if (symbol >= 29) { // Invalid fixed code return ErrorCode.ERR_INVALID_LENGTH_OR_DISTANCE_CODE; } (err, tempBits) = bits(s, lext[symbol]); if (err != ErrorCode.ERR_NONE) { return err; } len = lens[symbol] + tempBits; // Get and check distance (err, symbol) = _decode(s, distcode); if (err != ErrorCode.ERR_NONE) { // Invalid symbol return err; } (err, tempBits) = bits(s, dext[symbol]); if (err != ErrorCode.ERR_NONE) { return err; } dist = dists[symbol] + tempBits; if (dist > s.outcnt) { // Distance too far back return ErrorCode.ERR_DISTANCE_TOO_FAR; } // Copy length bytes from distance bytes back if (s.outcnt + len > s.output.length) { return ErrorCode.ERR_OUTPUT_EXHAUSTED; } while (len != 0) { // Note: Solidity reverts on underflow, so we decrement here len -= 1; s.output[s.outcnt] = s.output[s.outcnt - dist]; ++s.outcnt; } } else { s.outcnt += len; } } // Done with a valid fixed or dynamic block return ErrorCode.ERR_NONE; } } function _build_fixed(State memory s) private pure returns (ErrorCode) { unchecked { // Build fixed Huffman tables // TODO this is all a compile-time constant uint256 symbol; uint256[] memory lengths = new uint256[](FIXLCODES); // Literal/length table for (symbol = 0; symbol < 144; ++symbol) { lengths[symbol] = 8; } for (; symbol < 256; ++symbol) { lengths[symbol] = 9; } for (; symbol < 280; ++symbol) { lengths[symbol] = 7; } for (; symbol < FIXLCODES; ++symbol) { lengths[symbol] = 8; } _construct(s.lencode, lengths, FIXLCODES, 0); // Distance table for (symbol = 0; symbol < MAXDCODES; ++symbol) { lengths[symbol] = 5; } _construct(s.distcode, lengths, MAXDCODES, 0); return ErrorCode.ERR_NONE; } } function _fixed(State memory s) private pure returns (ErrorCode) { unchecked { // Decode data until end-of-block code return _codes(s, s.lencode, s.distcode); } } function _build_dynamic_lengths(State memory s) private pure returns (ErrorCode, uint256[] memory) { unchecked { uint256 ncode; // Index of lengths[] uint256 index; // Descriptor code lengths uint256[] memory lengths = new uint256[](MAXCODES); // Error code ErrorCode err; // Permutation of code length codes uint8[19] memory order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; (err, ncode) = bits(s, 4); if (err != ErrorCode.ERR_NONE) { return (err, lengths); } ncode += 4; // Read code length code lengths (really), missing lengths are zero for (index = 0; index < ncode; ++index) { (err, lengths[order[index]]) = bits(s, 3); if (err != ErrorCode.ERR_NONE) { return (err, lengths); } } for (; index < 19; ++index) { lengths[order[index]] = 0; } return (ErrorCode.ERR_NONE, lengths); } } function _build_dynamic(State memory s) private pure returns ( ErrorCode, Huffman memory, Huffman memory ) { unchecked { // Number of lengths in descriptor uint256 nlen; uint256 ndist; // Index of lengths[] uint256 index; // Error code ErrorCode err; // Descriptor code lengths uint256[] memory lengths = new uint256[](MAXCODES); // Length and distance codes Huffman memory lencode = Huffman(new uint256[](MAXBITS + 1), new uint256[](MAXLCODES)); Huffman memory distcode = Huffman(new uint256[](MAXBITS + 1), new uint256[](MAXDCODES)); uint256 tempBits; // Get number of lengths in each table, check lengths (err, nlen) = bits(s, 5); if (err != ErrorCode.ERR_NONE) { return (err, lencode, distcode); } nlen += 257; (err, ndist) = bits(s, 5); if (err != ErrorCode.ERR_NONE) { return (err, lencode, distcode); } ndist += 1; if (nlen > MAXLCODES || ndist > MAXDCODES) { // Bad counts return (ErrorCode.ERR_TOO_MANY_LENGTH_OR_DISTANCE_CODES, lencode, distcode); } (err, lengths) = _build_dynamic_lengths(s); if (err != ErrorCode.ERR_NONE) { return (err, lencode, distcode); } // Build huffman table for code lengths codes (use lencode temporarily) err = _construct(lencode, lengths, 19, 0); if (err != ErrorCode.ERR_NONE) { // Require complete code set here return (ErrorCode.ERR_CODE_LENGTHS_CODES_INCOMPLETE, lencode, distcode); } // Read length/literal and distance code length tables index = 0; while (index < nlen + ndist) { // Decoded value uint256 symbol; // Last length to repeat uint256 len; (err, symbol) = _decode(s, lencode); if (err != ErrorCode.ERR_NONE) { // Invalid symbol return (err, lencode, distcode); } if (symbol < 16) { // Length in 0..15 lengths[index++] = symbol; } else { // Repeat instruction // Assume repeating zeros len = 0; if (symbol == 16) { // Repeat last length 3..6 times if (index == 0) { // No last length! return (ErrorCode.ERR_REPEAT_NO_FIRST_LENGTH, lencode, distcode); } // Last length len = lengths[index - 1]; (err, tempBits) = bits(s, 2); if (err != ErrorCode.ERR_NONE) { return (err, lencode, distcode); } symbol = 3 + tempBits; } else if (symbol == 17) { // Repeat zero 3..10 times (err, tempBits) = bits(s, 3); if (err != ErrorCode.ERR_NONE) { return (err, lencode, distcode); } symbol = 3 + tempBits; } else { // == 18, repeat zero 11..138 times (err, tempBits) = bits(s, 7); if (err != ErrorCode.ERR_NONE) { return (err, lencode, distcode); } symbol = 11 + tempBits; } if (index + symbol > nlen + ndist) { // Too many lengths! return (ErrorCode.ERR_REPEAT_MORE, lencode, distcode); } while (symbol != 0) { // Note: Solidity reverts on underflow, so we decrement here symbol -= 1; // Repeat last or zero symbol times lengths[index++] = len; } } } // Check for end-of-block code -- there better be one! if (lengths[256] == 0) { return (ErrorCode.ERR_MISSING_END_OF_BLOCK, lencode, distcode); } // Build huffman table for literal/length codes err = _construct(lencode, lengths, nlen, 0); if ( err != ErrorCode.ERR_NONE && (err == ErrorCode.ERR_NOT_TERMINATED || err == ErrorCode.ERR_OUTPUT_EXHAUSTED || nlen != lencode.counts[0] + lencode.counts[1]) ) { // Incomplete code ok only for single length 1 code return (ErrorCode.ERR_INVALID_LITERAL_LENGTH_CODE_LENGTHS, lencode, distcode); } // Build huffman table for distance codes err = _construct(distcode, lengths, ndist, nlen); if ( err != ErrorCode.ERR_NONE && (err == ErrorCode.ERR_NOT_TERMINATED || err == ErrorCode.ERR_OUTPUT_EXHAUSTED || ndist != distcode.counts[0] + distcode.counts[1]) ) { // Incomplete code ok only for single length 1 code return (ErrorCode.ERR_INVALID_DISTANCE_CODE_LENGTHS, lencode, distcode); } return (ErrorCode.ERR_NONE, lencode, distcode); } } function _dynamic(State memory s) private pure returns (ErrorCode) { unchecked { // Length and distance codes Huffman memory lencode; Huffman memory distcode; // Error code ErrorCode err; (err, lencode, distcode) = _build_dynamic(s); if (err != ErrorCode.ERR_NONE) { return err; } // Decode data until end-of-block code return _codes(s, lencode, distcode); } } function puff(bytes memory source, uint256 destlen) internal pure returns (ErrorCode, bytes memory) { unchecked { // Input/output state State memory s = State( new bytes(destlen), 0, source, 0, 0, 0, Huffman(new uint256[](MAXBITS + 1), new uint256[](FIXLCODES)), Huffman(new uint256[](MAXBITS + 1), new uint256[](MAXDCODES)) ); // Temp: last bit uint256 last; // Temp: block type bit uint256 t; // Error code ErrorCode err; // Build fixed Huffman tables err = _build_fixed(s); if (err != ErrorCode.ERR_NONE) { return (err, s.output); } // Process blocks until last block or error while (last == 0) { // One if last block (err, last) = bits(s, 1); if (err != ErrorCode.ERR_NONE) { return (err, s.output); } // Block type 0..3 (err, t) = bits(s, 2); if (err != ErrorCode.ERR_NONE) { return (err, s.output); } err = ( t == 0 ? _stored(s) : (t == 1 ? _fixed(s) : (t == 2 ? _dynamic(s) : ErrorCode.ERR_INVALID_BLOCK_TYPE)) ); // type == 3, invalid if (err != ErrorCode.ERR_NONE) { // Return with error break; } } return (err, s.output); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; /// @title Base64 /// @author Brecht Devos - <[email protected]> /// @notice Provides functions for encoding/decoding base64 library Base64 { string internal constant TABLE_ENCODE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; bytes internal constant TABLE_DECODE = hex"0000000000000000000000000000000000000000000000000000000000000000" hex"00000000000000000000003e0000003f3435363738393a3b3c3d000000000000" hex"00000102030405060708090a0b0c0d0e0f101112131415161718190000000000" hex"001a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132330000000000"; function encode(bytes memory data) internal pure returns (string memory) { if (data.length == 0) return ''; // load the table into memory string memory table = TABLE_ENCODE; // multiply by 4/3 rounded up uint256 encodedLen = 4 * ((data.length + 2) / 3); // add some extra buffer at the end required for the writing string memory result = new string(encodedLen + 32); assembly { // set the actual output length mstore(result, encodedLen) // prepare the lookup table let tablePtr := add(table, 1) // input ptr let dataPtr := data let endPtr := add(dataPtr, mload(data)) // result ptr, jump over length let resultPtr := add(result, 32) // run over the input, 3 bytes at a time for {} lt(dataPtr, endPtr) {} { // read 3 bytes dataPtr := add(dataPtr, 3) let input := mload(dataPtr) // write 4 characters mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) resultPtr := add(resultPtr, 1) mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) resultPtr := add(resultPtr, 1) mstore8(resultPtr, mload(add(tablePtr, and(shr( 6, input), 0x3F)))) resultPtr := add(resultPtr, 1) mstore8(resultPtr, mload(add(tablePtr, and( input, 0x3F)))) resultPtr := add(resultPtr, 1) } // padding with '=' switch mod(mload(data), 3) case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) } case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) } } return result; } function decode(string memory _data) internal pure returns (bytes memory) { bytes memory data = bytes(_data); if (data.length == 0) return new bytes(0); require(data.length % 4 == 0, "invalid base64 decoder input"); // load the table into memory bytes memory table = TABLE_DECODE; // every 4 characters represent 3 bytes uint256 decodedLen = (data.length / 4) * 3; // add some extra buffer at the end required for the writing bytes memory result = new bytes(decodedLen + 32); assembly { // padding with '=' let lastBytes := mload(add(data, mload(data))) if eq(and(lastBytes, 0xFF), 0x3d) { decodedLen := sub(decodedLen, 1) if eq(and(lastBytes, 0xFFFF), 0x3d3d) { decodedLen := sub(decodedLen, 1) } } // set the actual output length mstore(result, decodedLen) // prepare the lookup table let tablePtr := add(table, 1) // input ptr let dataPtr := data let endPtr := add(dataPtr, mload(data)) // result ptr, jump over length let resultPtr := add(result, 32) // run over the input, 4 characters at a time for {} lt(dataPtr, endPtr) {} { // read 4 characters dataPtr := add(dataPtr, 4) let input := mload(dataPtr) // write 3 bytes let output := add( add( shl(18, and(mload(add(tablePtr, and(shr(24, input), 0xFF))), 0xFF)), shl(12, and(mload(add(tablePtr, and(shr(16, input), 0xFF))), 0xFF))), add( shl( 6, and(mload(add(tablePtr, and(shr( 8, input), 0xFF))), 0xFF)), and(mload(add(tablePtr, and( input , 0xFF))), 0xFF) ) ) mstore(resultPtr, shl(232, output)) resultPtr := add(resultPtr, 3) } } return result; } }
{ "optimizer": { "enabled": true, "runs": 10000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": { "contracts/libs/NFTDescriptorV2.sol": { "NFTDescriptorV2": "0x9e2325d8e05714e7e952c68f072552c12a500e91" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract INounsArt","name":"_art","type":"address"},{"internalType":"contract ISVGRenderer","name":"_renderer","type":"address"},{"internalType":"contract INounsComposer","name":"_composer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BadPaletteLength","type":"error"},{"inputs":[],"name":"EmptyPalette","type":"error"},{"inputs":[],"name":"IndexNotFound","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract INounsArt","name":"art","type":"address"}],"name":"ArtUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"baseURI","type":"string"}],"name":"BaseURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract INounsComposer","name":"renderer","type":"address"}],"name":"ComposerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"DataURIToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"PartsLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract ISVGRenderer","name":"renderer","type":"address"}],"name":"RendererUpdated","type":"event"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"accessories","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accessoryCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedCompressed","type":"bytes"},{"internalType":"uint80","name":"decompressedLength","type":"uint80"},{"internalType":"uint16","name":"imageCount","type":"uint16"}],"name":"addAccessories","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pointer","type":"address"},{"internalType":"uint80","name":"decompressedLength","type":"uint80"},{"internalType":"uint16","name":"imageCount","type":"uint16"}],"name":"addAccessoriesFromPointer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_background","type":"string"}],"name":"addBackground","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedCompressed","type":"bytes"},{"internalType":"uint80","name":"decompressedLength","type":"uint80"},{"internalType":"uint16","name":"imageCount","type":"uint16"}],"name":"addBodies","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pointer","type":"address"},{"internalType":"uint80","name":"decompressedLength","type":"uint80"},{"internalType":"uint16","name":"imageCount","type":"uint16"}],"name":"addBodiesFromPointer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedCompressed","type":"bytes"},{"internalType":"uint80","name":"decompressedLength","type":"uint80"},{"internalType":"uint16","name":"imageCount","type":"uint16"}],"name":"addGlasses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pointer","type":"address"},{"internalType":"uint80","name":"decompressedLength","type":"uint80"},{"internalType":"uint16","name":"imageCount","type":"uint16"}],"name":"addGlassesFromPointer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedCompressed","type":"bytes"},{"internalType":"uint80","name":"decompressedLength","type":"uint80"},{"internalType":"uint16","name":"imageCount","type":"uint16"}],"name":"addHeads","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pointer","type":"address"},{"internalType":"uint80","name":"decompressedLength","type":"uint80"},{"internalType":"uint16","name":"imageCount","type":"uint16"}],"name":"addHeadsFromPointer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string[]","name":"_backgrounds","type":"string[]"}],"name":"addManyBackgrounds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"arePartsLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"art","outputs":[{"internalType":"contract INounsArt","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"backgroundCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"backgrounds","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"bodies","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bodyCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"composer","outputs":[{"internalType":"contract INounsComposer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"uint48","name":"background","type":"uint48"},{"internalType":"uint48","name":"body","type":"uint48"},{"internalType":"uint48","name":"accessory","type":"uint48"},{"internalType":"uint48","name":"head","type":"uint48"},{"internalType":"uint48","name":"glasses","type":"uint48"}],"internalType":"struct INounsSeeder.Seed","name":"seed","type":"tuple"}],"name":"dataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"uint48","name":"background","type":"uint48"},{"internalType":"uint48","name":"body","type":"uint48"},{"internalType":"uint48","name":"accessory","type":"uint48"},{"internalType":"uint48","name":"head","type":"uint48"},{"internalType":"uint48","name":"glasses","type":"uint48"}],"internalType":"struct INounsSeeder.Seed","name":"seed","type":"tuple"}],"name":"generateSVGImage","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"description","type":"string"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"uint48","name":"background","type":"uint48"},{"internalType":"uint48","name":"body","type":"uint48"},{"internalType":"uint48","name":"accessory","type":"uint48"},{"internalType":"uint48","name":"head","type":"uint48"},{"internalType":"uint48","name":"glasses","type":"uint48"}],"internalType":"struct INounsSeeder.Seed","name":"seed","type":"tuple"}],"name":"genericDataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"uint48","name":"background","type":"uint48"},{"internalType":"uint48","name":"body","type":"uint48"},{"internalType":"uint48","name":"accessory","type":"uint48"},{"internalType":"uint48","name":"head","type":"uint48"},{"internalType":"uint48","name":"glasses","type":"uint48"}],"internalType":"struct INounsSeeder.Seed","name":"seed","type":"tuple"}],"name":"getPartsForSeed","outputs":[{"components":[{"internalType":"bytes","name":"image","type":"bytes"},{"internalType":"bytes","name":"palette","type":"bytes"}],"internalType":"struct ISVGRenderer.Part[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"glasses","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"glassesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"headCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"heads","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isDataURIEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockParts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"index","type":"uint8"}],"name":"palettes","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renderer","outputs":[{"internalType":"contract ISVGRenderer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract INounsArt","name":"_art","type":"address"}],"name":"setArt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"descriptor","type":"address"}],"name":"setArtDescriptor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IInflator","name":"inflator","type":"address"}],"name":"setArtInflator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract INounsComposer","name":"_composer","type":"address"}],"name":"setComposer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"paletteIndex","type":"uint8"},{"internalType":"bytes","name":"palette","type":"bytes"}],"name":"setPalette","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"paletteIndex","type":"uint8"},{"internalType":"address","name":"pointer","type":"address"}],"name":"setPalettePointer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISVGRenderer","name":"_renderer","type":"address"}],"name":"setRenderer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleDataURIEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"uint48","name":"background","type":"uint48"},{"internalType":"uint48","name":"body","type":"uint48"},{"internalType":"uint48","name":"accessory","type":"uint48"},{"internalType":"uint48","name":"head","type":"uint48"},{"internalType":"uint48","name":"glasses","type":"uint48"}],"internalType":"struct INounsSeeder.Seed","name":"seed","type":"tuple"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040526003805460ff60a81b1916600160a81b1790553480156200002457600080fd5b50604051620040b1380380620040b18339810160408190526200004791620000fe565b620000523362000095565b600180546001600160a01b039485166001600160a01b03199182161790915560028054938516938216939093179092556003805491909316911617905562000152565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114620000fb57600080fd5b50565b6000806000606084860312156200011457600080fd5b83516200012181620000e5565b60208501519093506200013481620000e5565b60408501519092506200014781620000e5565b809150509250925092565b613f4f80620001626000396000f3fe608060405234801561001057600080fd5b50600436106102ff5760003560e01c806373ac736b1161019c578063aeb1fe51116100ee578063dfe8478b11610097578063eba8180611610071578063eba8180614610648578063f2fde38b14610650578063f4513a6a1461066357600080fd5b8063dfe8478b1461061a578063e6b1a3ae14610622578063e79c9ea61461063557600080fd5b8063cc2aa091116100c8578063cc2aa091146105d9578063cd2b8250146105e1578063ce2f4f53146105f457600080fd5b8063aeb1fe51146105a0578063b982d1b9146105b3578063bc2d45fe146105c657600080fd5b80638bd54c061161015057806394f3df611161012a57806394f3df611461055a578063aa5bf7d81461056d578063ac6712f01461058057600080fd5b80638bd54c06146105235780638da5cb5b1461053657806391b7916a1461054757600080fd5b8063791bac4811610181578063791bac48146104ea5780637ca94210146104fd5780638ada6b0f1461051057600080fd5b806373ac736b146104a2578063773b9771146104b557600080fd5b8063461fc5af116102555780635e70664c116102095780636c0360eb116101e35780636c0360eb1461047f5780636e85653114610487578063715018a61461049a57600080fd5b80635e70664c14610446578063638ac270146104595780636af044951461046c57600080fd5b806355f804b31161023a57806355f804b31461040d57806356d3163d146104205780635a503f131461043357600080fd5b8063461fc5af146103f25780634daebac21461040557600080fd5b8063301bd28e116102b75780634479cef2116102915780634479cef2146103c157806344cee73c146103d75780634531c0a8146103ea57600080fd5b8063301bd28e14610370578063353c36a01461039b5780633cfdafd3146103ae57600080fd5b80630ba3db1a116102e85780630ba3db1a146103425780632a1d0769146103555780632f46e15f1461035d57600080fd5b8063010ecde71461030457806304bde4dd14610319575b600080fd5b610317610312366004612e6d565b610676565b005b61032c610327366004612e91565b610751565b6040516103399190612f06565b60405180910390f35b610317610350366004612f8a565b6107e2565b61031761092e565b61032c61036b3660046131c8565b610a5d565b600154610383906001600160a01b031681565b6040516001600160a01b039091168152602001610339565b6103176103a9366004612f8a565b610bd1565b61032c6103bc366004613248565b610ce5565b6103c9610d50565b604051908152602001610339565b61032c6103e5366004612e91565b610de3565b6103c9610e6f565b610317610400366004613275565b610efb565b6103c961105a565b61031761041b3660046132c0565b6110bc565b61031761042e366004612e6d565b611161565b61032c610441366004612e91565b611228565b6103176104543660046132c0565b611273565b61032c610467366004613248565b6113b9565b61032c61047a366004613248565b61141c565b61032c611582565b610317610495366004613275565b611610565b61031761173c565b6103176104b0366004613275565b6117a2565b6003546104da9074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610339565b6103176104f8366004612e6d565b6118ce565b61032c61050b366004612e91565b61198e565b600254610383906001600160a01b031681565b610317610531366004613313565b6119d9565b6000546001600160a01b0316610383565b61031761055536600461334a565b611af2565b610317610568366004612f8a565b611c02565b61031761057b366004612f8a565b611d16565b61059361058e366004613248565b611e2a565b60405161033991906133bf565b600354610383906001600160a01b031681565b61032c6105c1366004612e91565b61252b565b61032c6105d4366004613462565b612576565b6103c96125c3565b6103176105ef366004613275565b612625565b6003546104da907501000000000000000000000000000000000000000000900460ff1681565b610317612751565b610317610630366004612e6d565b612828565b61031761064336600461347d565b612953565b6103c9612a65565b61031761065e366004612e6d565b612ac7565b610317610671366004612e6d565b612ba9565b6000546001600160a01b031633146106d55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6001546040517f01b9a3970000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152909116906301b9a397906024015b600060405180830381600087803b15801561073657600080fd5b505af115801561074a573d6000803e3d6000fd5b5050505050565b6001546040517f04bde4dd000000000000000000000000000000000000000000000000000000008152600481018390526060916001600160a01b0316906304bde4dd90602401600060405180830381865afa1580156107b4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107dc9190810190613500565b92915050565b6000546001600160a01b0316331461083c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156108a75760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f0ba3db1a0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690630ba3db1a906108f6908790879087908790600401613574565b600060405180830381600087803b15801561091057600080fd5b505af1158015610924573d6000803e3d6000fd5b5050505050505050565b6000546001600160a01b031633146109885760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156109f35760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b600380547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f1680ee6d421f70ed6030d2fc4fcb50217a5dd617858d56562b119eca59172e5790600090a1565b6040805160808101825285815260208101859052600154835183517f04bde4dd00000000000000000000000000000000000000000000000000000000815265ffffffffffff909116600482015260609360009392908301916001600160a01b03909116906304bde4dd90602401600060405180830381865afa158015610ae7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b0f9190810190613500565b8152602001610b1e8686611e2a565b90526002546040517f92ba0e90000000000000000000000000000000000000000000000000000000008152919250739e2325d8e05714e7e952c68f072552c12a500e91916392ba0e9091610b82916001600160a01b0390911690859060040161362a565b600060405180830381865af4158015610b9f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bc79190810190613500565b9695505050505050565b6000546001600160a01b03163314610c2b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615610c965760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f353c36a00000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063353c36a0906108f6908790879087908790600401613574565b6003546060907501000000000000000000000000000000000000000000900460ff1615610d1d57610d1683836113b9565b90506107dc565b6004610d2884612c4e565b604051602001610d3992919061371f565b604051602081830303815290604052905092915050565b600154604080517fe73dd38300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163e73dd38391600480830192869291908290030181865afa158015610db2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dda91908101906137e8565b60200151905090565b6001546040517f44cee73c000000000000000000000000000000000000000000000000000000008152600481018390526060916001600160a01b0316906344cee73c906024015b600060405180830381865afa158015610e47573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107dc919081019061391c565b600154604080517ffd30704b00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163fd30704b9160048083019260209291908290030181865afa158015610ed2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef69190613951565b905090565b6000546001600160a01b03163314610f555760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615610fc05760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f461fc5af0000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015269ffffffffffffffffffff8516602483015261ffff841660448301529091169063461fc5af906064015b600060405180830381600087803b15801561103d57600080fd5b505af1158015611051573d6000803e3d6000fd5b50505050505050565b600154604080517fc64b2f5d00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c64b2f5d91600480830192869291908290030181865afa158015610db2573d6000803e3d6000fd5b6000546001600160a01b031633146111165760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60046111238284836139b5565b507f6741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad8282604051611155929190613ab1565b60405180910390a15050565b6000546001600160a01b031633146111bb5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f482cbbbcf912da3be80deb8503ae1e94c0b7d5d1d0ec0af3d9d6403e06e609ee906020015b60405180910390a150565b6001546040517f5a503f13000000000000000000000000000000000000000000000000000000008152600481018390526060916001600160a01b031690635a503f1390602401610e2a565b6000546001600160a01b031633146112cd5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156113385760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f5e70664c0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690635e70664c906113839085908590600401613ab1565b600060405180830381600087803b15801561139d57600080fd5b505af11580156113b1573d6000803e3d6000fd5b505050505050565b606060006113c684612c4e565b90506000816040516020016113db9190613ac5565b60405160208183030381529060405290506000826040516020016113ff9190613b0a565b6040516020818303038152906040529050610bc782828888610a5d565b6060600060405180604001604052806114358686611e2a565b815260015485516040517f04bde4dd00000000000000000000000000000000000000000000000000000000815265ffffffffffff90911660048201526020909201916001600160a01b03909116906304bde4dd90602401600060405180830381865afa1580156114a9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114d19190810190613500565b90526002546040517f22cc1ad6000000000000000000000000000000000000000000000000000000008152919250739e2325d8e05714e7e952c68f072552c12a500e91916322cc1ad691611535916001600160a01b03909116908590600401613b9c565b600060405180830381865af4158015611552573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261157a9190810190613500565b949350505050565b6004805461158f906136cc565b80601f01602080910402602001604051908101604052809291908181526020018280546115bb906136cc565b80156116085780601f106115dd57610100808354040283529160200191611608565b820191906000526020600020905b8154815290600101906020018083116115eb57829003601f168201915b505050505081565b6000546001600160a01b0316331461166a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156116d55760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f6e8565310000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015269ffffffffffffffffffff8516602483015261ffff8416604483015290911690636e85653190606401611023565b6000546001600160a01b031633146117965760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b6117a06000612d83565b565b6000546001600160a01b031633146117fc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156118675760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f73ac736b0000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015269ffffffffffffffffffff8516602483015261ffff84166044830152909116906373ac736b90606401611023565b6000546001600160a01b031633146119285760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527fcc8fd63e29484d2c3569420344203147ecd5019fe031a751317fe4fb015c1f119060200161121d565b6001546040517f7ca94210000000000000000000000000000000000000000000000000000000008152600481018390526060916001600160a01b031690637ca9421090602401610e2a565b6000546001600160a01b03163314611a335760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615611a9e5760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f8bd54c0600000000000000000000000000000000000000000000000000000000815260ff841660048201526001600160a01b03838116602483015290911690638bd54c0690604401611383565b6000546001600160a01b03163314611b4c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615611bb75760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f91b7916a0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906391b7916a906113839085908590600401613c01565b6000546001600160a01b03163314611c5c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615611cc75760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f94f3df610000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906394f3df61906108f6908790879087908790600401613574565b6000546001600160a01b03163314611d705760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615611ddb5760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517faa5bf7d80000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063aa5bf7d8906108f6908790879087908790600401613574565b60015460208201516040517f44cee73c00000000000000000000000000000000000000000000000000000000815265ffffffffffff90911660048201526060916000916001600160a01b03909116906344cee73c90602401600060405180830381865afa158015611e9f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ec7919081019061391c565b60015460408581015190517f7ca9421000000000000000000000000000000000000000000000000000000000815265ffffffffffff90911660048201529192506000916001600160a01b0390911690637ca9421090602401600060405180830381865afa158015611f3c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611f64919081019061391c565b60015460608601516040517f5a503f1300000000000000000000000000000000000000000000000000000000815265ffffffffffff90911660048201529192506000916001600160a01b0390911690635a503f1390602401600060405180830381865afa158015611fd9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612001919081019061391c565b60015460808701516040517fb982d1b900000000000000000000000000000000000000000000000000000000815265ffffffffffff90911660048201529192506000916001600160a01b039091169063b982d1b990602401600060405180830381865afa158015612076573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261209e919081019061391c565b60408051600480825260a0820190925291925060009190816020015b60408051808201909152606080825260208201528152602001906001900390816120ba57905050905060405180604001604052808681526020016120fd87612deb565b8152508160008151811061211357612113613ccb565b6020026020010181905250604051806040016040528085815260200161213886612deb565b8152508160018151811061214e5761214e613ccb565b6020026020010181905250604051806040016040528084815260200161217385612deb565b8152508160028151811061218957612189613ccb565b602002602001018190525060405180604001604052808381526020016121ae84612deb565b815250816003815181106121c4576121c4613ccb565b60209081029190910101526003546040517fc5d57fd8000000000000000000000000000000000000000000000000000000008152600481018a90526000916001600160a01b03169063c5d57fd890602401600060405180830381865afa158015612232573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261225a9190810190613cfa565b8051909150600c81101561227757829750505050505050506107dc565b8160048151811061228a5761228a613ccb565b602002602001015160000151516000036122d857826000815181106122b1576122b1613ccb565b6020026020010151826004815181106122cc576122cc613ccb565b60200260200101819052505b816006815181106122eb576122eb613ccb565b60200260200101516000015151600003612339578260018151811061231257612312613ccb565b60200260200101518260068151811061232d5761232d613ccb565b60200260200101819052505b8160088151811061234c5761234c613ccb565b6020026020010151600001515160000361239a578260028151811061237357612373613ccb565b60200260200101518260088151811061238e5761238e613ccb565b60200260200101819052505b81600a815181106123ad576123ad613ccb565b602002602001015160000151516000036123fb57826003815181106123d4576123d4613ccb565b602002602001015182600a815181106123ef576123ef613ccb565b60200260200101819052505b6000805b8281101561243d57600084828151811061241b5761241b613ccb565b602002602001015160000151511115612435576001909101905b6001016123ff565b506000808267ffffffffffffffff81111561245a5761245a612ff2565b60405190808252806020026020018201604052801561249f57816020015b60408051808201909152606080825260208201528152602001906001900390816124785790505b50905060005b8481101561251a5760008682815181106124c1576124c1613ccb565b602002602001015160000151511115612512578581815181106124e6576124e6613ccb565b602002602001015182848151811061250057612500613ccb565b60209081029190910101526001909201915b6001016124a5565b509c9b505050505050505050505050565b6001546040517fb982d1b9000000000000000000000000000000000000000000000000000000008152600481018390526060916001600160a01b03169063b982d1b990602401610e2a565b6001546040517fbc2d45fe00000000000000000000000000000000000000000000000000000000815260ff831660048201526060916001600160a01b03169063bc2d45fe90602401610e2a565b600154604080517f368013dc00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163368013dc91600480830192869291908290030181865afa158015610db2573d6000803e3d6000fd5b6000546001600160a01b0316331461267f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156126ea5760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517fcd2b82500000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015269ffffffffffffffffffff8516602483015261ffff841660448301529091169063cd2b825090606401611023565b6000546001600160a01b031633146127ab5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b600380547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff811675010000000000000000000000000000000000000000009182900460ff1615918202179091556040518181527f360c3d72ee193226275b842f85231c259c934e85459fed80fa68e502ffa9dbde9060200161121d565b6000546001600160a01b031633146128825760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156128ed5760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f89382d75256b43b6826ad8d6cbd8e517eaf5e10f1ef4c8f123c9a25ac4529b559060200161121d565b6000546001600160a01b031633146129ad5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615612a185760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517fe79c9ea60000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063e79c9ea69061102390869086908690600401613e06565b600154604080517f222a36d000000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163222a36d091600480830192869291908290030181865afa158015610db2573d6000803e3d6000fd5b6000546001600160a01b03163314612b215760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b6001600160a01b038116612b9d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106cc565b612ba681612d83565b50565b6000546001600160a01b03163314612c035760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b6001546040517f72aa4a960000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152909116906372aa4a969060240161071c565b606081600003612c9157505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115612cbb5780612ca581613e5b565b9150612cb49050600a83613ec2565b9150612c95565b60008167ffffffffffffffff811115612cd657612cd6612ff2565b6040519080825280601f01601f191660200182016040528015612d00576020820181803683370190505b5090505b841561157a57612d15600183613ed6565b9150612d22600a86613eed565b612d2d906030613f01565b60f81b818381518110612d4257612d42613ccb565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612d7c600a86613ec2565b9450612d04565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60015481516060916001600160a01b03169063bc2d45fe908490600090612e1457612e14613ccb565b01602001516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815260f89190911c6004820152602401610e2a565b6001600160a01b0381168114612ba657600080fd5b600060208284031215612e7f57600080fd5b8135612e8a81612e58565b9392505050565b600060208284031215612ea357600080fd5b5035919050565b60005b83811015612ec5578181015183820152602001612ead565b83811115612ed4576000848401525b50505050565b60008151808452612ef2816020860160208601612eaa565b601f01601f19169290920160200192915050565b602081526000612e8a6020830184612eda565b60008083601f840112612f2b57600080fd5b50813567ffffffffffffffff811115612f4357600080fd5b602083019150836020828501011115612f5b57600080fd5b9250929050565b69ffffffffffffffffffff81168114612ba657600080fd5b61ffff81168114612ba657600080fd5b60008060008060608587031215612fa057600080fd5b843567ffffffffffffffff811115612fb757600080fd5b612fc387828801612f19565b9095509350506020850135612fd781612f62565b91506040850135612fe781612f7a565b939692955090935050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561304457613044612ff2565b60405290565b6040516060810167ffffffffffffffff8111828210171561304457613044612ff2565b604051601f8201601f1916810167ffffffffffffffff8111828210171561309657613096612ff2565b604052919050565b600067ffffffffffffffff8211156130b8576130b8612ff2565b50601f01601f191660200190565b600082601f8301126130d757600080fd5b81356130ea6130e58261309e565b61306d565b8181528460208386010111156130ff57600080fd5b816020850160208301376000918101602001919091529392505050565b803565ffffffffffff8116811461313257600080fd5b919050565b600060a0828403121561314957600080fd5b60405160a0810181811067ffffffffffffffff8211171561316c5761316c612ff2565b60405290508061317b8361311c565b81526131896020840161311c565b602082015261319a6040840161311c565b60408201526131ab6060840161311c565b60608201526131bc6080840161311c565b60808201525092915050565b60008060008061010085870312156131df57600080fd5b843567ffffffffffffffff808211156131f757600080fd5b613203888389016130c6565b9550602087013591508082111561321957600080fd5b50613226878288016130c6565b9350506040850135915061323d8660608701613137565b905092959194509250565b60008060c0838503121561325b57600080fd5b8235915061326c8460208501613137565b90509250929050565b60008060006060848603121561328a57600080fd5b833561329581612e58565b925060208401356132a581612f62565b915060408401356132b581612f7a565b809150509250925092565b600080602083850312156132d357600080fd5b823567ffffffffffffffff8111156132ea57600080fd5b6132f685828601612f19565b90969095509350505050565b803560ff8116811461313257600080fd5b6000806040838503121561332657600080fd5b61332f83613302565b9150602083013561333f81612e58565b809150509250929050565b6000806020838503121561335d57600080fd5b823567ffffffffffffffff8082111561337557600080fd5b818501915085601f83011261338957600080fd5b81358181111561339857600080fd5b8660208260051b85010111156133ad57600080fd5b60209290920196919550909350505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015613454577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08984030185528151805187855261342888860182612eda565b91890151858303868b01529190506134408183612eda565b9689019694505050908601906001016133e6565b509098975050505050505050565b60006020828403121561347457600080fd5b612e8a82613302565b60008060006040848603121561349257600080fd5b61349b84613302565b9250602084013567ffffffffffffffff8111156134b757600080fd5b6134c386828701612f19565b9497909650939450505050565b60006134de6130e58461309e565b90508281528383830111156134f257600080fd5b612e8a836020830184612eaa565b60006020828403121561351257600080fd5b815167ffffffffffffffff81111561352957600080fd5b8201601f8101841361353a57600080fd5b61157a848251602084016134d0565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b606081526000613588606083018688613549565b905069ffffffffffffffffffff8416602083015261ffff8316604083015295945050505050565b600081518084526020808501808196508360051b8101915082860160005b8581101561361d5782840389528151604081518187526135ef82880182612eda565b915050868201519150858103878701526136098183612eda565b9a87019a95505050908401906001016135cd565b5091979650505050505050565b6001600160a01b038316815260406020820152600082516080604084015261365560c0840182612eda565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0808584030160608601526136918383612eda565b925060408601519150808584030160808601526136ae8383612eda565b925060608601519150808584030160a086015250610bc782826135af565b600181811c908216806136e057607f821691505b602082108103613719577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600080845461372d816136cc565b600182811680156137455760018114613778576137a7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841687528215158302870194506137a7565b8860005260208060002060005b8581101561379e5781548a820152908401908201613785565b50505082870194505b5050505083516137bb818360208801612eaa565b01949350505050565b600067ffffffffffffffff8211156137de576137de612ff2565b5060051b60200190565b600060208083850312156137fb57600080fd5b825167ffffffffffffffff8082111561381357600080fd5b8185019150604080838803121561382957600080fd5b613831613021565b83518381111561384057600080fd5b84019250601f8301881361385357600080fd5b82516138616130e5826137c4565b8181526060918202850187019187820191908b84111561388057600080fd5b958801955b838710156138e35780878d03121561389d5760008081fd5b6138a561304a565b87516138b081612f7a565b8152878a01516138bf81612f62565b818b0152878701516138d081612e58565b8188015283529586019591880191613885565b5083525050928401519383019390935250949350505050565b600082601f83011261390d57600080fd5b612e8a838351602085016134d0565b60006020828403121561392e57600080fd5b815167ffffffffffffffff81111561394557600080fd5b61157a848285016138fc565b60006020828403121561396357600080fd5b5051919050565b601f8211156139b057600081815260208120601f850160051c810160208610156139915750805b601f850160051c820191505b818110156113b15782815560010161399d565b505050565b67ffffffffffffffff8311156139cd576139cd612ff2565b6139e1836139db83546136cc565b8361396a565b6000601f841160018114613a3357600085156139fd5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b17835561074a565b600083815260209020601f19861690835b82811015613a645786850135825560209485019460019092019101613a44565b5086821015613a9f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152600061157a602083018486613549565b7f4358204e6f756e20000000000000000000000000000000000000000000000000815260008251613afd816008850160208701612eaa565b9190910160080192915050565b7f4358204e6f756e20000000000000000000000000000000000000000000000000815260008251613b42816008850160208701612eaa565b7f2069732061206d656d626572206f662074686520436f6d706f7361626c65732060089390910192830152507f44414f00000000000000000000000000000000000000000000000000000000006028820152602b01919050565b6001600160a01b03831681526040602082015260008251604080840152613bc660808401826135af565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0848303016060850152610bc78282612eda565b60208082528181018390526000906040600585901b8401810190840186845b8781101561361d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc087850301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18a3603018112613c8157600080fd5b8901858101903567ffffffffffffffff811115613c9d57600080fd5b803603821315613cac57600080fd5b613cb7868284613549565b955050509184019190840190600101613c20565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020808385031215613d0d57600080fd5b825167ffffffffffffffff80821115613d2557600080fd5b818501915085601f830112613d3957600080fd5b8151613d476130e5826137c4565b81815260059190911b83018401908481019088831115613d6657600080fd5b8585015b83811015613df957805185811115613d825760008081fd5b86016040818c03601f1901811315613d9a5760008081fd5b613da2613021565b8983015188811115613db45760008081fd5b613dc28e8c838701016138fc565b825250908201519087821115613dd85760008081fd5b613de68d8b848601016138fc565b818b015285525050918601918601613d6a565b5098975050505050505050565b60ff84168152604060208201526000613e23604083018486613549565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613e8c57613e8c613e2c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613ed157613ed1613e93565b500490565b600082821015613ee857613ee8613e2c565b500390565b600082613efc57613efc613e93565b500690565b60008219821115613f1457613f14613e2c565b50019056fea26469706673582212200827072c6ea9e29a08178ea8123f99d46749b6c19f34b237d515888923ce477564736f6c634300080f003300000000000000000000000048a7c62e2560d1336869d6550841222942768c4900000000000000000000000081d94554a4b072bfcd850205f0c79e97c92aab56000000000000000000000000306748345c14432eef311d231b4bd98594def9ee
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102ff5760003560e01c806373ac736b1161019c578063aeb1fe51116100ee578063dfe8478b11610097578063eba8180611610071578063eba8180614610648578063f2fde38b14610650578063f4513a6a1461066357600080fd5b8063dfe8478b1461061a578063e6b1a3ae14610622578063e79c9ea61461063557600080fd5b8063cc2aa091116100c8578063cc2aa091146105d9578063cd2b8250146105e1578063ce2f4f53146105f457600080fd5b8063aeb1fe51146105a0578063b982d1b9146105b3578063bc2d45fe146105c657600080fd5b80638bd54c061161015057806394f3df611161012a57806394f3df611461055a578063aa5bf7d81461056d578063ac6712f01461058057600080fd5b80638bd54c06146105235780638da5cb5b1461053657806391b7916a1461054757600080fd5b8063791bac4811610181578063791bac48146104ea5780637ca94210146104fd5780638ada6b0f1461051057600080fd5b806373ac736b146104a2578063773b9771146104b557600080fd5b8063461fc5af116102555780635e70664c116102095780636c0360eb116101e35780636c0360eb1461047f5780636e85653114610487578063715018a61461049a57600080fd5b80635e70664c14610446578063638ac270146104595780636af044951461046c57600080fd5b806355f804b31161023a57806355f804b31461040d57806356d3163d146104205780635a503f131461043357600080fd5b8063461fc5af146103f25780634daebac21461040557600080fd5b8063301bd28e116102b75780634479cef2116102915780634479cef2146103c157806344cee73c146103d75780634531c0a8146103ea57600080fd5b8063301bd28e14610370578063353c36a01461039b5780633cfdafd3146103ae57600080fd5b80630ba3db1a116102e85780630ba3db1a146103425780632a1d0769146103555780632f46e15f1461035d57600080fd5b8063010ecde71461030457806304bde4dd14610319575b600080fd5b610317610312366004612e6d565b610676565b005b61032c610327366004612e91565b610751565b6040516103399190612f06565b60405180910390f35b610317610350366004612f8a565b6107e2565b61031761092e565b61032c61036b3660046131c8565b610a5d565b600154610383906001600160a01b031681565b6040516001600160a01b039091168152602001610339565b6103176103a9366004612f8a565b610bd1565b61032c6103bc366004613248565b610ce5565b6103c9610d50565b604051908152602001610339565b61032c6103e5366004612e91565b610de3565b6103c9610e6f565b610317610400366004613275565b610efb565b6103c961105a565b61031761041b3660046132c0565b6110bc565b61031761042e366004612e6d565b611161565b61032c610441366004612e91565b611228565b6103176104543660046132c0565b611273565b61032c610467366004613248565b6113b9565b61032c61047a366004613248565b61141c565b61032c611582565b610317610495366004613275565b611610565b61031761173c565b6103176104b0366004613275565b6117a2565b6003546104da9074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610339565b6103176104f8366004612e6d565b6118ce565b61032c61050b366004612e91565b61198e565b600254610383906001600160a01b031681565b610317610531366004613313565b6119d9565b6000546001600160a01b0316610383565b61031761055536600461334a565b611af2565b610317610568366004612f8a565b611c02565b61031761057b366004612f8a565b611d16565b61059361058e366004613248565b611e2a565b60405161033991906133bf565b600354610383906001600160a01b031681565b61032c6105c1366004612e91565b61252b565b61032c6105d4366004613462565b612576565b6103c96125c3565b6103176105ef366004613275565b612625565b6003546104da907501000000000000000000000000000000000000000000900460ff1681565b610317612751565b610317610630366004612e6d565b612828565b61031761064336600461347d565b612953565b6103c9612a65565b61031761065e366004612e6d565b612ac7565b610317610671366004612e6d565b612ba9565b6000546001600160a01b031633146106d55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6001546040517f01b9a3970000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152909116906301b9a397906024015b600060405180830381600087803b15801561073657600080fd5b505af115801561074a573d6000803e3d6000fd5b5050505050565b6001546040517f04bde4dd000000000000000000000000000000000000000000000000000000008152600481018390526060916001600160a01b0316906304bde4dd90602401600060405180830381865afa1580156107b4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107dc9190810190613500565b92915050565b6000546001600160a01b0316331461083c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156108a75760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f0ba3db1a0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690630ba3db1a906108f6908790879087908790600401613574565b600060405180830381600087803b15801561091057600080fd5b505af1158015610924573d6000803e3d6000fd5b5050505050505050565b6000546001600160a01b031633146109885760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156109f35760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b600380547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f1680ee6d421f70ed6030d2fc4fcb50217a5dd617858d56562b119eca59172e5790600090a1565b6040805160808101825285815260208101859052600154835183517f04bde4dd00000000000000000000000000000000000000000000000000000000815265ffffffffffff909116600482015260609360009392908301916001600160a01b03909116906304bde4dd90602401600060405180830381865afa158015610ae7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b0f9190810190613500565b8152602001610b1e8686611e2a565b90526002546040517f92ba0e90000000000000000000000000000000000000000000000000000000008152919250739e2325d8e05714e7e952c68f072552c12a500e91916392ba0e9091610b82916001600160a01b0390911690859060040161362a565b600060405180830381865af4158015610b9f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bc79190810190613500565b9695505050505050565b6000546001600160a01b03163314610c2b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615610c965760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f353c36a00000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063353c36a0906108f6908790879087908790600401613574565b6003546060907501000000000000000000000000000000000000000000900460ff1615610d1d57610d1683836113b9565b90506107dc565b6004610d2884612c4e565b604051602001610d3992919061371f565b604051602081830303815290604052905092915050565b600154604080517fe73dd38300000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163e73dd38391600480830192869291908290030181865afa158015610db2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dda91908101906137e8565b60200151905090565b6001546040517f44cee73c000000000000000000000000000000000000000000000000000000008152600481018390526060916001600160a01b0316906344cee73c906024015b600060405180830381865afa158015610e47573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107dc919081019061391c565b600154604080517ffd30704b00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163fd30704b9160048083019260209291908290030181865afa158015610ed2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef69190613951565b905090565b6000546001600160a01b03163314610f555760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615610fc05760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f461fc5af0000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015269ffffffffffffffffffff8516602483015261ffff841660448301529091169063461fc5af906064015b600060405180830381600087803b15801561103d57600080fd5b505af1158015611051573d6000803e3d6000fd5b50505050505050565b600154604080517fc64b2f5d00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163c64b2f5d91600480830192869291908290030181865afa158015610db2573d6000803e3d6000fd5b6000546001600160a01b031633146111165760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60046111238284836139b5565b507f6741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad8282604051611155929190613ab1565b60405180910390a15050565b6000546001600160a01b031633146111bb5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f482cbbbcf912da3be80deb8503ae1e94c0b7d5d1d0ec0af3d9d6403e06e609ee906020015b60405180910390a150565b6001546040517f5a503f13000000000000000000000000000000000000000000000000000000008152600481018390526060916001600160a01b031690635a503f1390602401610e2a565b6000546001600160a01b031633146112cd5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156113385760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f5e70664c0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690635e70664c906113839085908590600401613ab1565b600060405180830381600087803b15801561139d57600080fd5b505af11580156113b1573d6000803e3d6000fd5b505050505050565b606060006113c684612c4e565b90506000816040516020016113db9190613ac5565b60405160208183030381529060405290506000826040516020016113ff9190613b0a565b6040516020818303038152906040529050610bc782828888610a5d565b6060600060405180604001604052806114358686611e2a565b815260015485516040517f04bde4dd00000000000000000000000000000000000000000000000000000000815265ffffffffffff90911660048201526020909201916001600160a01b03909116906304bde4dd90602401600060405180830381865afa1580156114a9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114d19190810190613500565b90526002546040517f22cc1ad6000000000000000000000000000000000000000000000000000000008152919250739e2325d8e05714e7e952c68f072552c12a500e91916322cc1ad691611535916001600160a01b03909116908590600401613b9c565b600060405180830381865af4158015611552573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261157a9190810190613500565b949350505050565b6004805461158f906136cc565b80601f01602080910402602001604051908101604052809291908181526020018280546115bb906136cc565b80156116085780601f106115dd57610100808354040283529160200191611608565b820191906000526020600020905b8154815290600101906020018083116115eb57829003601f168201915b505050505081565b6000546001600160a01b0316331461166a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156116d55760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f6e8565310000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015269ffffffffffffffffffff8516602483015261ffff8416604483015290911690636e85653190606401611023565b6000546001600160a01b031633146117965760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b6117a06000612d83565b565b6000546001600160a01b031633146117fc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156118675760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f73ac736b0000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015269ffffffffffffffffffff8516602483015261ffff84166044830152909116906373ac736b90606401611023565b6000546001600160a01b031633146119285760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527fcc8fd63e29484d2c3569420344203147ecd5019fe031a751317fe4fb015c1f119060200161121d565b6001546040517f7ca94210000000000000000000000000000000000000000000000000000000008152600481018390526060916001600160a01b031690637ca9421090602401610e2a565b6000546001600160a01b03163314611a335760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615611a9e5760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f8bd54c0600000000000000000000000000000000000000000000000000000000815260ff841660048201526001600160a01b03838116602483015290911690638bd54c0690604401611383565b6000546001600160a01b03163314611b4c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615611bb75760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f91b7916a0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906391b7916a906113839085908590600401613c01565b6000546001600160a01b03163314611c5c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615611cc75760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517f94f3df610000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906394f3df61906108f6908790879087908790600401613574565b6000546001600160a01b03163314611d705760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615611ddb5760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517faa5bf7d80000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063aa5bf7d8906108f6908790879087908790600401613574565b60015460208201516040517f44cee73c00000000000000000000000000000000000000000000000000000000815265ffffffffffff90911660048201526060916000916001600160a01b03909116906344cee73c90602401600060405180830381865afa158015611e9f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ec7919081019061391c565b60015460408581015190517f7ca9421000000000000000000000000000000000000000000000000000000000815265ffffffffffff90911660048201529192506000916001600160a01b0390911690637ca9421090602401600060405180830381865afa158015611f3c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611f64919081019061391c565b60015460608601516040517f5a503f1300000000000000000000000000000000000000000000000000000000815265ffffffffffff90911660048201529192506000916001600160a01b0390911690635a503f1390602401600060405180830381865afa158015611fd9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612001919081019061391c565b60015460808701516040517fb982d1b900000000000000000000000000000000000000000000000000000000815265ffffffffffff90911660048201529192506000916001600160a01b039091169063b982d1b990602401600060405180830381865afa158015612076573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261209e919081019061391c565b60408051600480825260a0820190925291925060009190816020015b60408051808201909152606080825260208201528152602001906001900390816120ba57905050905060405180604001604052808681526020016120fd87612deb565b8152508160008151811061211357612113613ccb565b6020026020010181905250604051806040016040528085815260200161213886612deb565b8152508160018151811061214e5761214e613ccb565b6020026020010181905250604051806040016040528084815260200161217385612deb565b8152508160028151811061218957612189613ccb565b602002602001018190525060405180604001604052808381526020016121ae84612deb565b815250816003815181106121c4576121c4613ccb565b60209081029190910101526003546040517fc5d57fd8000000000000000000000000000000000000000000000000000000008152600481018a90526000916001600160a01b03169063c5d57fd890602401600060405180830381865afa158015612232573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261225a9190810190613cfa565b8051909150600c81101561227757829750505050505050506107dc565b8160048151811061228a5761228a613ccb565b602002602001015160000151516000036122d857826000815181106122b1576122b1613ccb565b6020026020010151826004815181106122cc576122cc613ccb565b60200260200101819052505b816006815181106122eb576122eb613ccb565b60200260200101516000015151600003612339578260018151811061231257612312613ccb565b60200260200101518260068151811061232d5761232d613ccb565b60200260200101819052505b8160088151811061234c5761234c613ccb565b6020026020010151600001515160000361239a578260028151811061237357612373613ccb565b60200260200101518260088151811061238e5761238e613ccb565b60200260200101819052505b81600a815181106123ad576123ad613ccb565b602002602001015160000151516000036123fb57826003815181106123d4576123d4613ccb565b602002602001015182600a815181106123ef576123ef613ccb565b60200260200101819052505b6000805b8281101561243d57600084828151811061241b5761241b613ccb565b602002602001015160000151511115612435576001909101905b6001016123ff565b506000808267ffffffffffffffff81111561245a5761245a612ff2565b60405190808252806020026020018201604052801561249f57816020015b60408051808201909152606080825260208201528152602001906001900390816124785790505b50905060005b8481101561251a5760008682815181106124c1576124c1613ccb565b602002602001015160000151511115612512578581815181106124e6576124e6613ccb565b602002602001015182848151811061250057612500613ccb565b60209081029190910101526001909201915b6001016124a5565b509c9b505050505050505050505050565b6001546040517fb982d1b9000000000000000000000000000000000000000000000000000000008152600481018390526060916001600160a01b03169063b982d1b990602401610e2a565b6001546040517fbc2d45fe00000000000000000000000000000000000000000000000000000000815260ff831660048201526060916001600160a01b03169063bc2d45fe90602401610e2a565b600154604080517f368013dc00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163368013dc91600480830192869291908290030181865afa158015610db2573d6000803e3d6000fd5b6000546001600160a01b0316331461267f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156126ea5760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517fcd2b82500000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015269ffffffffffffffffffff8516602483015261ffff841660448301529091169063cd2b825090606401611023565b6000546001600160a01b031633146127ab5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b600380547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff811675010000000000000000000000000000000000000000009182900460ff1615918202179091556040518181527f360c3d72ee193226275b842f85231c259c934e85459fed80fa68e502ffa9dbde9060200161121d565b6000546001600160a01b031633146128825760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff16156128ed5760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527f89382d75256b43b6826ad8d6cbd8e517eaf5e10f1ef4c8f123c9a25ac4529b559060200161121d565b6000546001600160a01b031633146129ad5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b60035474010000000000000000000000000000000000000000900460ff1615612a185760405162461bcd60e51b815260206004820152601060248201527f506172747320617265206c6f636b65640000000000000000000000000000000060448201526064016106cc565b6001546040517fe79c9ea60000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063e79c9ea69061102390869086908690600401613e06565b600154604080517f222a36d000000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163222a36d091600480830192869291908290030181865afa158015610db2573d6000803e3d6000fd5b6000546001600160a01b03163314612b215760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b6001600160a01b038116612b9d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106cc565b612ba681612d83565b50565b6000546001600160a01b03163314612c035760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cc565b6001546040517f72aa4a960000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152909116906372aa4a969060240161071c565b606081600003612c9157505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115612cbb5780612ca581613e5b565b9150612cb49050600a83613ec2565b9150612c95565b60008167ffffffffffffffff811115612cd657612cd6612ff2565b6040519080825280601f01601f191660200182016040528015612d00576020820181803683370190505b5090505b841561157a57612d15600183613ed6565b9150612d22600a86613eed565b612d2d906030613f01565b60f81b818381518110612d4257612d42613ccb565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612d7c600a86613ec2565b9450612d04565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60015481516060916001600160a01b03169063bc2d45fe908490600090612e1457612e14613ccb565b01602001516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815260f89190911c6004820152602401610e2a565b6001600160a01b0381168114612ba657600080fd5b600060208284031215612e7f57600080fd5b8135612e8a81612e58565b9392505050565b600060208284031215612ea357600080fd5b5035919050565b60005b83811015612ec5578181015183820152602001612ead565b83811115612ed4576000848401525b50505050565b60008151808452612ef2816020860160208601612eaa565b601f01601f19169290920160200192915050565b602081526000612e8a6020830184612eda565b60008083601f840112612f2b57600080fd5b50813567ffffffffffffffff811115612f4357600080fd5b602083019150836020828501011115612f5b57600080fd5b9250929050565b69ffffffffffffffffffff81168114612ba657600080fd5b61ffff81168114612ba657600080fd5b60008060008060608587031215612fa057600080fd5b843567ffffffffffffffff811115612fb757600080fd5b612fc387828801612f19565b9095509350506020850135612fd781612f62565b91506040850135612fe781612f7a565b939692955090935050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561304457613044612ff2565b60405290565b6040516060810167ffffffffffffffff8111828210171561304457613044612ff2565b604051601f8201601f1916810167ffffffffffffffff8111828210171561309657613096612ff2565b604052919050565b600067ffffffffffffffff8211156130b8576130b8612ff2565b50601f01601f191660200190565b600082601f8301126130d757600080fd5b81356130ea6130e58261309e565b61306d565b8181528460208386010111156130ff57600080fd5b816020850160208301376000918101602001919091529392505050565b803565ffffffffffff8116811461313257600080fd5b919050565b600060a0828403121561314957600080fd5b60405160a0810181811067ffffffffffffffff8211171561316c5761316c612ff2565b60405290508061317b8361311c565b81526131896020840161311c565b602082015261319a6040840161311c565b60408201526131ab6060840161311c565b60608201526131bc6080840161311c565b60808201525092915050565b60008060008061010085870312156131df57600080fd5b843567ffffffffffffffff808211156131f757600080fd5b613203888389016130c6565b9550602087013591508082111561321957600080fd5b50613226878288016130c6565b9350506040850135915061323d8660608701613137565b905092959194509250565b60008060c0838503121561325b57600080fd5b8235915061326c8460208501613137565b90509250929050565b60008060006060848603121561328a57600080fd5b833561329581612e58565b925060208401356132a581612f62565b915060408401356132b581612f7a565b809150509250925092565b600080602083850312156132d357600080fd5b823567ffffffffffffffff8111156132ea57600080fd5b6132f685828601612f19565b90969095509350505050565b803560ff8116811461313257600080fd5b6000806040838503121561332657600080fd5b61332f83613302565b9150602083013561333f81612e58565b809150509250929050565b6000806020838503121561335d57600080fd5b823567ffffffffffffffff8082111561337557600080fd5b818501915085601f83011261338957600080fd5b81358181111561339857600080fd5b8660208260051b85010111156133ad57600080fd5b60209290920196919550909350505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015613454577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08984030185528151805187855261342888860182612eda565b91890151858303868b01529190506134408183612eda565b9689019694505050908601906001016133e6565b509098975050505050505050565b60006020828403121561347457600080fd5b612e8a82613302565b60008060006040848603121561349257600080fd5b61349b84613302565b9250602084013567ffffffffffffffff8111156134b757600080fd5b6134c386828701612f19565b9497909650939450505050565b60006134de6130e58461309e565b90508281528383830111156134f257600080fd5b612e8a836020830184612eaa565b60006020828403121561351257600080fd5b815167ffffffffffffffff81111561352957600080fd5b8201601f8101841361353a57600080fd5b61157a848251602084016134d0565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b606081526000613588606083018688613549565b905069ffffffffffffffffffff8416602083015261ffff8316604083015295945050505050565b600081518084526020808501808196508360051b8101915082860160005b8581101561361d5782840389528151604081518187526135ef82880182612eda565b915050868201519150858103878701526136098183612eda565b9a87019a95505050908401906001016135cd565b5091979650505050505050565b6001600160a01b038316815260406020820152600082516080604084015261365560c0840182612eda565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0808584030160608601526136918383612eda565b925060408601519150808584030160808601526136ae8383612eda565b925060608601519150808584030160a086015250610bc782826135af565b600181811c908216806136e057607f821691505b602082108103613719577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600080845461372d816136cc565b600182811680156137455760018114613778576137a7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841687528215158302870194506137a7565b8860005260208060002060005b8581101561379e5781548a820152908401908201613785565b50505082870194505b5050505083516137bb818360208801612eaa565b01949350505050565b600067ffffffffffffffff8211156137de576137de612ff2565b5060051b60200190565b600060208083850312156137fb57600080fd5b825167ffffffffffffffff8082111561381357600080fd5b8185019150604080838803121561382957600080fd5b613831613021565b83518381111561384057600080fd5b84019250601f8301881361385357600080fd5b82516138616130e5826137c4565b8181526060918202850187019187820191908b84111561388057600080fd5b958801955b838710156138e35780878d03121561389d5760008081fd5b6138a561304a565b87516138b081612f7a565b8152878a01516138bf81612f62565b818b0152878701516138d081612e58565b8188015283529586019591880191613885565b5083525050928401519383019390935250949350505050565b600082601f83011261390d57600080fd5b612e8a838351602085016134d0565b60006020828403121561392e57600080fd5b815167ffffffffffffffff81111561394557600080fd5b61157a848285016138fc565b60006020828403121561396357600080fd5b5051919050565b601f8211156139b057600081815260208120601f850160051c810160208610156139915750805b601f850160051c820191505b818110156113b15782815560010161399d565b505050565b67ffffffffffffffff8311156139cd576139cd612ff2565b6139e1836139db83546136cc565b8361396a565b6000601f841160018114613a3357600085156139fd5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b17835561074a565b600083815260209020601f19861690835b82811015613a645786850135825560209485019460019092019101613a44565b5086821015613a9f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152600061157a602083018486613549565b7f4358204e6f756e20000000000000000000000000000000000000000000000000815260008251613afd816008850160208701612eaa565b9190910160080192915050565b7f4358204e6f756e20000000000000000000000000000000000000000000000000815260008251613b42816008850160208701612eaa565b7f2069732061206d656d626572206f662074686520436f6d706f7361626c65732060089390910192830152507f44414f00000000000000000000000000000000000000000000000000000000006028820152602b01919050565b6001600160a01b03831681526040602082015260008251604080840152613bc660808401826135af565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0848303016060850152610bc78282612eda565b60208082528181018390526000906040600585901b8401810190840186845b8781101561361d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc087850301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18a3603018112613c8157600080fd5b8901858101903567ffffffffffffffff811115613c9d57600080fd5b803603821315613cac57600080fd5b613cb7868284613549565b955050509184019190840190600101613c20565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020808385031215613d0d57600080fd5b825167ffffffffffffffff80821115613d2557600080fd5b818501915085601f830112613d3957600080fd5b8151613d476130e5826137c4565b81815260059190911b83018401908481019088831115613d6657600080fd5b8585015b83811015613df957805185811115613d825760008081fd5b86016040818c03601f1901811315613d9a5760008081fd5b613da2613021565b8983015188811115613db45760008081fd5b613dc28e8c838701016138fc565b825250908201519087821115613dd85760008081fd5b613de68d8b848601016138fc565b818b015285525050918601918601613d6a565b5098975050505050505050565b60ff84168152604060208201526000613e23604083018486613549565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613e8c57613e8c613e2c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613ed157613ed1613e93565b500490565b600082821015613ee857613ee8613e2c565b500390565b600082613efc57613efc613e93565b500690565b60008219821115613f1457613f14613e2c565b50019056fea26469706673582212200827072c6ea9e29a08178ea8123f99d46749b6c19f34b237d515888923ce477564736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000048a7c62e2560d1336869d6550841222942768c4900000000000000000000000081d94554a4b072bfcd850205f0c79e97c92aab56000000000000000000000000306748345c14432eef311d231b4bd98594def9ee
-----Decoded View---------------
Arg [0] : _art (address): 0x48A7C62e2560d1336869D6550841222942768C49
Arg [1] : _renderer (address): 0x81d94554A4b072BFcd850205f0c79e97c92aab56
Arg [2] : _composer (address): 0x306748345C14432eEF311d231b4bD98594def9Ee
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000048a7c62e2560d1336869d6550841222942768c49
Arg [1] : 00000000000000000000000081d94554a4b072bfcd850205f0c79e97c92aab56
Arg [2] : 000000000000000000000000306748345c14432eef311d231b4bd98594def9ee
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.