false
true
0

Contract Address Details

0x192ce8267CbaB9C3C477D61e85D7f0c5fE3B46Af

Contract Name
EditionMetadataRenderer
Creator
0xad031e–1b3671 at 0x6c76ef–094fda
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
25872966
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
EditionMetadataRenderer




Optimization enabled
true
Compiler version
v0.8.10+commit.fc410830




Optimization runs
5000
EVM Version
london




Verified at
2026-02-24T14:04:16.753562Z

src/metadata/EditionMetadataRenderer.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

import {IMetadataRenderer} from "../interfaces/IMetadataRenderer.sol";
import {IERC721Drop} from "../interfaces/IERC721Drop.sol";
import {IERC721MetadataUpgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC721MetadataUpgradeable.sol";
import {IERC2981Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC2981Upgradeable.sol";
import {NFTMetadataRenderer} from "../utils/NFTMetadataRenderer.sol";
import {MetadataRenderAdminCheck} from "./MetadataRenderAdminCheck.sol";

interface DropConfigGetter {
    function config()
        external
        view
        returns (IERC721Drop.Configuration memory config);
}

/// @notice EditionMetadataRenderer for editions support
contract EditionMetadataRenderer is
    IMetadataRenderer,
    MetadataRenderAdminCheck
{
    /// @notice Storage for token edition information
    struct TokenEditionInfo {
        string description;
        string imageURI;
        string animationURI;
    }

    /// @notice Event for updated Media URIs
    event MediaURIsUpdated(
        address indexed target,
        address sender,
        string imageURI,
        string animationURI
    );

    /// @notice Event for a new edition initialized
    /// @dev admin function indexer feedback
    event EditionInitialized(
        address indexed target,
        string description,
        string imageURI,
        string animationURI
    );

    /// @notice Description updated for this edition
    /// @dev admin function indexer feedback
    event DescriptionUpdated(
        address indexed target,
        address sender,
        string newDescription
    );

    /// @notice Token information mapping storage
    mapping(address => TokenEditionInfo) public tokenInfos;

    /// @notice Update media URIs
    /// @param target target for contract to update metadata for
    /// @param imageURI new image uri address
    /// @param animationURI new animation uri address
    function updateMediaURIs(
        address target,
        string memory imageURI,
        string memory animationURI
    ) external requireSenderAdmin(target) {
        tokenInfos[target].imageURI = imageURI;
        tokenInfos[target].animationURI = animationURI;
        emit MediaURIsUpdated({
            target: target,
            sender: msg.sender,
            imageURI: imageURI,
            animationURI: animationURI
        });
    }

    /// @notice Admin function to update description
    /// @param target target description
    /// @param newDescription new description
    function updateDescription(address target, string memory newDescription)
        external
        requireSenderAdmin(target)
    {
        tokenInfos[target].description = newDescription;

        emit DescriptionUpdated({
            target: target,
            sender: msg.sender,
            newDescription: newDescription
        });
    }

    /// @notice Default initializer for edition data from a specific contract
    /// @param data data to init with
    function initializeWithData(bytes memory data) external {
        // data format: description, imageURI, animationURI
        (
            string memory description,
            string memory imageURI,
            string memory animationURI
        ) = abi.decode(data, (string, string, string));

        tokenInfos[msg.sender] = TokenEditionInfo({
            description: description,
            imageURI: imageURI,
            animationURI: animationURI
        });
        emit EditionInitialized({
            target: msg.sender,
            description: description,
            imageURI: imageURI,
            animationURI: animationURI
        });
    }

    /// @notice Contract URI information getter
    /// @return contract uri (if set)
    function contractURI() external view override returns (string memory) {
        address target = msg.sender;
        TokenEditionInfo storage editionInfo = tokenInfos[target];
        IERC721Drop.Configuration memory config = DropConfigGetter(target)
            .config();

        return
            NFTMetadataRenderer.encodeContractURIJSON({
                name: IERC721MetadataUpgradeable(target).name(),
                description: editionInfo.description,
                imageURI: editionInfo.imageURI,
                animationURI: editionInfo.animationURI,
                royaltyBPS: uint256(config.royaltyBPS),
                royaltyRecipient: config.fundsRecipient
            });
    }

    /// @notice Token URI information getter
    /// @param tokenId to get uri for
    /// @return contract uri (if set)
    function tokenURI(uint256 tokenId)
        external
        view
        override
        returns (string memory)
    {
        address target = msg.sender;

        TokenEditionInfo memory info = tokenInfos[target];
        IERC721Drop media = IERC721Drop(target);

        uint256 maxSupply = media.saleDetails().maxSupply;

        // For open editions, set max supply to 0 for renderer to remove the edition max number
        // This will be added back on once the open edition is "finalized"
        if (maxSupply == type(uint64).max) {
            maxSupply = 0;
        }

        return
            NFTMetadataRenderer.createMetadataEdition({
                name: IERC721MetadataUpgradeable(target).name(),
                description: info.description,
                imageURI: info.imageURI,
                animationURI: info.animationURI,
                tokenOfEdition: tokenId,
                editionSize: maxSupply
            });
    }
}
        

/

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

interface IMetadataRenderer {
    function tokenURI(uint256) external view returns (string memory);
    function contractURI() external view returns (string memory);
    function initializeWithData(bytes memory initData) external;
}
          

/

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

import {IMetadataRenderer} from "../interfaces/IMetadataRenderer.sol";

/**

 ________   _____   ____    ______      ____
/\_____  \ /\  __`\/\  _`\ /\  _  \    /\  _`\
\/____//'/'\ \ \/\ \ \ \L\ \ \ \L\ \   \ \ \/\ \  _ __   ___   _____     ____
     //'/'  \ \ \ \ \ \ ,  /\ \  __ \   \ \ \ \ \/\`'__\/ __`\/\ '__`\  /',__\
    //'/'___ \ \ \_\ \ \ \\ \\ \ \/\ \   \ \ \_\ \ \ \//\ \L\ \ \ \L\ \/\__, `\
    /\_______\\ \_____\ \_\ \_\ \_\ \_\   \ \____/\ \_\\ \____/\ \ ,__/\/\____/
    \/_______/ \/_____/\/_/\/ /\/_/\/_/    \/___/  \/_/ \/___/  \ \ \/  \/___/
                                                                 \ \_\
                                                                  \/_/

*/

/// @notice Interface for ZORA Drops contract
interface IERC721Drop {
    // Access errors

    /// @notice Only admin can access this function
    error Access_OnlyAdmin();
    /// @notice Missing the given role or admin access
    error Access_MissingRoleOrAdmin(bytes32 role);
    /// @notice Withdraw is not allowed by this user
    error Access_WithdrawNotAllowed();
    /// @notice Cannot withdraw funds due to ETH send failure.
    error Withdraw_FundsSendFailure();

    // Sale/Purchase errors
    /// @notice Sale is inactive
    error Sale_Inactive();
    /// @notice Presale is inactive
    error Presale_Inactive();
    /// @notice Presale merkle root is invalid
    error Presale_MerkleNotApproved();
    /// @notice Wrong price for purchase
    error Purchase_WrongPrice(uint256 correctPrice);
    /// @notice NFT sold out
    error Mint_SoldOut();
    /// @notice Too many purchase for address
    error Purchase_TooManyForAddress();
    /// @notice Too many presale for address
    error Presale_TooManyForAddress();

    // Admin errors
    /// @notice Royalty percentage too high
    error Setup_RoyaltyPercentageTooHigh(uint16 maxRoyaltyBPS);
    /// @notice Invalid admin upgrade address
    error Admin_InvalidUpgradeAddress(address proposedAddress);
    /// @notice Unable to finalize an edition not marked as open (size set to uint64_max_value)
    error Admin_UnableToFinalizeNotOpenEdition();

    /// @notice Event emitted for each sale
    /// @param to address sale was made to
    /// @param quantity quantity of the minted nfts
    /// @param pricePerToken price for each token
    /// @param firstPurchasedTokenId first purchased token ID (to get range add to quantity for max)
    event Sale(
        address indexed to,
        uint256 indexed quantity,
        uint256 indexed pricePerToken,
        uint256 firstPurchasedTokenId
    );

    /// @notice Sales configuration has been changed
    /// @dev To access new sales configuration, use getter function.
    /// @param changedBy Changed by user
    event SalesConfigChanged(address indexed changedBy);

    /// @notice Event emitted when the funds recipient is changed
    /// @param newAddress new address for the funds recipient
    /// @param changedBy address that the recipient is changed by
    event FundsRecipientChanged(
        address indexed newAddress,
        address indexed changedBy
    );

    /// @notice Event emitted when the funds are withdrawn from the minting contract
    /// @param withdrawnBy address that issued the withdraw
    /// @param withdrawnTo address that the funds were withdrawn to
    /// @param amount amount that was withdrawn
    /// @param feeRecipient user getting withdraw fee (if any)
    /// @param feeAmount amount of the fee getting sent (if any)
    event FundsWithdrawn(
        address indexed withdrawnBy,
        address indexed withdrawnTo,
        uint256 amount,
        address feeRecipient,
        uint256 feeAmount
    );

    /// @notice Event emitted when an open mint is finalized and further minting is closed forever on the contract.
    /// @param sender address sending close mint
    /// @param numberOfMints number of mints the contract is finalized at
    event OpenMintFinalized(address indexed sender, uint256 numberOfMints);

    /// @notice Event emitted when metadata renderer is updated.
    /// @param sender address of the updater
    /// @param renderer new metadata renderer address
    event UpdatedMetadataRenderer(address sender, IMetadataRenderer renderer);


    /// @notice General configuration for NFT Minting and bookkeeping
    struct Configuration {
        /// @dev Metadata renderer (uint160)
        IMetadataRenderer metadataRenderer;
        /// @dev Total size of edition that can be minted (uint160+64 = 224)
        uint64 editionSize;
        /// @dev Royalty amount in bps (uint224+16 = 240)
        uint16 royaltyBPS;
        /// @dev Funds recipient for sale (new slot, uint160)
        address payable fundsRecipient;
    }

    /// @notice Sales states and configuration
    /// @dev Uses 3 storage slots
    struct SalesConfiguration {
        /// @dev Public sale price (max ether value > 1000 ether with this value)
        uint104 publicSalePrice;
        /// @notice Purchase mint limit per address (if set to 0 === unlimited mints)
        /// @dev Max purchase number per txn (90+32 = 122)
        uint32 maxSalePurchasePerAddress;
        /// @dev uint64 type allows for dates into 292 billion years
        /// @notice Public sale start timestamp (136+64 = 186)
        uint64 publicSaleStart;
        /// @notice Public sale end timestamp (186+64 = 250)
        uint64 publicSaleEnd;
        /// @notice Presale start timestamp
        /// @dev new storage slot
        uint64 presaleStart;
        /// @notice Presale end timestamp
        uint64 presaleEnd;
        /// @notice Presale merkle root
        bytes32 presaleMerkleRoot;
    }

    /// @notice Return value for sales details to use with front-ends
    struct SaleDetails {
        // Synthesized status variables for sale and presale
        bool publicSaleActive;
        bool presaleActive;
        // Price for public sale
        uint256 publicSalePrice;
        // Timed sale actions for public sale
        uint64 publicSaleStart;
        uint64 publicSaleEnd;
        // Timed sale actions for presale
        uint64 presaleStart;
        uint64 presaleEnd;
        // Merkle root (includes address, quantity, and price data for each entry)
        bytes32 presaleMerkleRoot;
        // Limit public sale to a specific number of mints per wallet
        uint256 maxSalePurchasePerAddress;
        // Information about the rest of the supply
        // Total that have been minted
        uint256 totalMinted;
        // The total supply available
        uint256 maxSupply;
    }

    /// @notice Return type of specific mint counts and details per address
    struct AddressMintDetails {
        /// Number of total mints from the given address
        uint256 totalMints;
        /// Number of presale mints from the given address
        uint256 presaleMints;
        /// Number of public mints from the given address
        uint256 publicMints;
    }

    /// @notice External purchase function (payable in eth)
    /// @param quantity to purchase
    /// @return first minted token ID
    function purchase(uint256 quantity) external payable returns (uint256);

    /// @notice External purchase presale function (takes a merkle proof and matches to root) (payable in eth)
    /// @param quantity to purchase
    /// @param maxQuantity can purchase (verified by merkle root)
    /// @param pricePerToken price per token allowed (verified by merkle root)
    /// @param merkleProof input for merkle proof leaf verified by merkle root
    /// @return first minted token ID
    function purchasePresale(
        uint256 quantity,
        uint256 maxQuantity,
        uint256 pricePerToken,
        bytes32[] memory merkleProof
    ) external payable returns (uint256);

    /// @notice Function to return the global sales details for the given drop
    function saleDetails() external view returns (SaleDetails memory);

    /// @notice Function to return the specific sales details for a given address
    /// @param minter address for minter to return mint information for
    function mintedPerAddress(address minter)
        external
        view
        returns (AddressMintDetails memory);

    /// @notice This is the opensea/public owner setting that can be set by the contract admin
    function owner() external view returns (address);

    /// @notice Update the metadata renderer
    /// @param newRenderer new address for renderer
    /// @param setupRenderer data to call to bootstrap data for the new renderer (optional)
    function setMetadataRenderer(IMetadataRenderer newRenderer, bytes memory setupRenderer) external;

    /// @notice This is an admin mint function to mint a quantity to a specific address
    /// @param to address to mint to
    /// @param quantity quantity to mint
    /// @return the id of the first minted NFT
    function adminMint(address to, uint256 quantity) external returns (uint256);

    /// @notice This is an admin mint function to mint a single nft each to a list of addresses
    /// @param to list of addresses to mint an NFT each to
    /// @return the id of the first minted NFT
    function adminMintAirdrop(address[] memory to) external returns (uint256);

    /// @dev Getter for admin role associated with the contract to handle metadata
    /// @return boolean if address is admin
    function isAdmin(address user) external view returns (bool);
}
          

/introspection/IERC165Upgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165Upgradeable {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
          

/ERC721/extensions/IERC721MetadataUpgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC721Upgradeable.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721MetadataUpgradeable is IERC721Upgradeable {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}
          

/IERC721MetadataUpgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../token/ERC721/extensions/IERC721MetadataUpgradeable.sol";
          

/Base64.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Base64.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides a set of functions to operate with Base64 strings.
 *
 * _Available since v4.5._
 */
library Base64 {
    /**
     * @dev Base64 Encoding/Decoding Table
     */
    string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    /**
     * @dev Converts a `bytes` to its Bytes64 `string` representation.
     */
    function encode(bytes memory data) internal pure returns (string memory) {
        /**
         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
         */
        if (data.length == 0) return "";

        // Loads the table into memory
        string memory table = _TABLE;

        // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter
        // and split into 4 numbers of 6 bits.
        // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up
        // - `data.length + 2`  -> Round up
        // - `/ 3`              -> Number of 3-bytes chunks
        // - `4 *`              -> 4 characters for each chunk
        string memory result = new string(4 * ((data.length + 2) / 3));

        assembly {
            // Prepare the lookup table (skip the first "length" byte)
            let tablePtr := add(table, 1)

            // Prepare result pointer, jump over length
            let resultPtr := add(result, 32)

            // Run over the input, 3 bytes at a time
            for {
                let dataPtr := data
                let endPtr := add(data, mload(data))
            } lt(dataPtr, endPtr) {

            } {
                // Advance 3 bytes
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                // To write each character, shift the 3 bytes (18 bits) chunk
                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
                // and apply logical AND with 0x3F which is the number of
                // the previous character in the ASCII table prior to the Base64 Table
                // The result is then added to the table to get the character to write,
                // and finally write it in the result pointer but with a left shift
                // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits

                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance
            }

            // When data `bytes` is not exactly 3 bytes long
            // it is padded with `=` characters at the end
            switch mod(mload(data), 3)
            case 1 {
                mstore8(sub(resultPtr, 1), 0x3d)
                mstore8(sub(resultPtr, 2), 0x3d)
            }
            case 2 {
                mstore8(sub(resultPtr, 1), 0x3d)
            }
        }

        return result;
    }
}
          

/

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {Base64} from "@openzeppelin/contracts/utils/Base64.sol";

/// NFT metadata library for rendering metadata associated with editions
library NFTMetadataRenderer {
    /// Generate edition metadata from storage information as base64-json blob
    /// Combines the media data and metadata
    /// @param name Name of NFT in metadata
    /// @param description Description of NFT in metadata
    /// @param imageURI URI of image to render for edition
    /// @param animationURI URI of animation to render for edition
    /// @param tokenOfEdition Token ID for specific token
    /// @param editionSize Size of entire edition to show
    function createMetadataEdition(
        string memory name,
        string memory description,
        string memory imageURI,
        string memory animationURI,
        uint256 tokenOfEdition,
        uint256 editionSize
    ) internal pure returns (string memory) {
        string memory _tokenMediaData = tokenMediaData(
            imageURI,
            animationURI
        );
        bytes memory json = createMetadataJSON(
            name,
            description,
            _tokenMediaData,
            tokenOfEdition,
            editionSize
        );
        return encodeMetadataJSON(json);
    }

    function encodeContractURIJSON(
        string memory name,
        string memory description,
        string memory imageURI,
        string memory animationURI,
        uint256 royaltyBPS,
        address royaltyRecipient
    ) internal pure returns (string memory) {
        bytes memory imageSpace = bytes("");
        if (bytes(imageURI).length > 0) {
            imageSpace = abi.encodePacked('", "image": "', imageURI);
        }
        bytes memory animationSpace = bytes("");
        if (bytes(animationURI).length > 0) {
            animationSpace = abi.encodePacked('", "animation_url": "', animationURI);
        }

        return
            string(
                encodeMetadataJSON(
                    abi.encodePacked(
                        '{"name": "',
                        name,
                        '", "description": "',
                        description,
                        // this is for opensea since they don't respect ERC2981 right now
                        '", "seller_fee_basis_points": ',
                        Strings.toString(royaltyBPS),
                        ', "fee_recipient": "',
                        Strings.toHexString(uint256(uint160(royaltyRecipient)), 20),
                        imageSpace,
                        animationSpace,
                        '"}'
                    )
                )
            );
    }

    /// Function to create the metadata json string for the nft edition
    /// @param name Name of NFT in metadata
    /// @param description Description of NFT in metadata
    /// @param mediaData Data for media to include in json object
    /// @param tokenOfEdition Token ID for specific token
    /// @param editionSize Size of entire edition to show
    function createMetadataJSON(
        string memory name,
        string memory description,
        string memory mediaData,
        uint256 tokenOfEdition,
        uint256 editionSize
    ) internal pure returns (bytes memory) {
        bytes memory editionSizeText;
        if (editionSize > 0) {
            editionSizeText = abi.encodePacked(
                "/",
                Strings.toString(editionSize)
            );
        }
        return
            abi.encodePacked(
                '{"name": "',
                name,
                " ",
                Strings.toString(tokenOfEdition),
                editionSizeText,
                '", "',
                'description": "',
                description,
                '", "',
                mediaData,
                'properties": {"number": ',
                Strings.toString(tokenOfEdition),
                ', "name": "',
                name,
                '"}}'
            );
    }

    /// Encodes the argument json bytes into base64-data uri format
    /// @param json Raw json to base64 and turn into a data-uri
    function encodeMetadataJSON(bytes memory json)
        internal
        pure
        returns (string memory)
    {
        return
            string(
                abi.encodePacked(
                    "data:application/json;base64,",
                    Base64.encode(json)
                )
            );
    }

    /// Generates edition metadata from storage information as base64-json blob
    /// Combines the media data and metadata
    /// @param imageUrl URL of image to render for edition
    /// @param animationUrl URL of animation to render for edition
    function tokenMediaData(
        string memory imageUrl,
        string memory animationUrl
    ) internal pure returns (string memory) {
        bool hasImage = bytes(imageUrl).length > 0;
        bool hasAnimation = bytes(animationUrl).length > 0;
        if (hasImage && hasAnimation) {
            return
                string(
                    abi.encodePacked(
                        'image": "',
                        imageUrl,
                        '", "animation_url": "',
                        animationUrl,
                        '", "'
                    )
                );
        }
        if (hasImage) {
            return string(abi.encodePacked('image": "', imageUrl, '", "'));
        }
        if (hasAnimation) {
            return
                string(
                    abi.encodePacked('animation_url": "', animationUrl, '", "')
                );
        }

        return "";
    }
}
          

/

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

import {IERC721Drop} from "../interfaces/IERC721Drop.sol";

contract MetadataRenderAdminCheck {
    error Access_OnlyAdmin();

    /// @notice Modifier to require the sender to be an admin
    /// @param target address that the user wants to modify
    modifier requireSenderAdmin(address target) {
        if (target != msg.sender && !IERC721Drop(target).isAdmin(msg.sender)) {
            revert Access_OnlyAdmin();
        }

        _;
    }
}
          

/ERC721/IERC721Upgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165Upgradeable.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721Upgradeable is IERC165Upgradeable {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}
          

/IERC2981Upgradeable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.0;

import "../utils/introspection/IERC165Upgradeable.sol";

/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981Upgradeable is IERC165Upgradeable {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be payed in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}
          

/Strings.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}
          

Compiler Settings

{"remappings":[":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",":ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/",":base64/=lib/base64/",":ds-test/=lib/ds-test/src/",":erc721a-upgradeable/=lib/ERC721A-Upgradeable/contracts/",":forge-std/=lib/forge-std/src/",":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",":openzeppelin-contracts/=lib/openzeppelin-contracts/"],"optimizer":{"runs":5000,"enabled":true},"metadata":{"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"london","compilationTarget":{"src/metadata/EditionMetadataRenderer.sol":"EditionMetadataRenderer"}}
              

Contract ABI

[{"type":"error","name":"Access_OnlyAdmin","inputs":[]},{"type":"event","name":"DescriptionUpdated","inputs":[{"type":"address","name":"target","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":false},{"type":"string","name":"newDescription","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"EditionInitialized","inputs":[{"type":"address","name":"target","internalType":"address","indexed":true},{"type":"string","name":"description","internalType":"string","indexed":false},{"type":"string","name":"imageURI","internalType":"string","indexed":false},{"type":"string","name":"animationURI","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"MediaURIsUpdated","inputs":[{"type":"address","name":"target","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":false},{"type":"string","name":"imageURI","internalType":"string","indexed":false},{"type":"string","name":"animationURI","internalType":"string","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"contractURI","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initializeWithData","inputs":[{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"description","internalType":"string"},{"type":"string","name":"imageURI","internalType":"string"},{"type":"string","name":"animationURI","internalType":"string"}],"name":"tokenInfos","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"tokenURI","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateDescription","inputs":[{"type":"address","name":"target","internalType":"address"},{"type":"string","name":"newDescription","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateMediaURIs","inputs":[{"type":"address","name":"target","internalType":"address"},{"type":"string","name":"imageURI","internalType":"string"},{"type":"string","name":"animationURI","internalType":"string"}]}]
              

Contract Creation Code

0x608060405234801561001057600080fd5b506121ff806100206000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063ba46ae7211610050578063ba46ae72146100b2578063c87b56dd146100dd578063e8a3d485146100fd57600080fd5b80632f17b8f014610077578063856a7ffa1461008c5780638bbb2cf21461009f575b600080fd5b61008a610085366004611569565b610105565b005b61008a61009a3660046115df565b6102bc565b61008a6100ad366004611628565b61038b565b6100c56100c0366004611678565b6104fe565b6040516100d4939291906116f1565b60405180910390f35b6100f06100eb36600461172a565b6106b8565b6040516100d49190611743565b6100f06109b5565b8273ffffffffffffffffffffffffffffffffffffffff811633148015906101b757506040517f24d7806c00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216906324d7806c90602401602060405180830381865afa158015610191573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101b5919061176b565b155b156101ee576040517f02bd6bd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526020818152604090912084516102289260019092019186019061139b565b5073ffffffffffffffffffffffffffffffffffffffff841660009081526020818152604090912083516102639260029092019185019061139b565b508373ffffffffffffffffffffffffffffffffffffffff167fc4c1b9223fcebe5f35b9030d3df655018c40e88d70b8a3c63ed851c5d972210f3385856040516102ae93929190611786565b60405180910390a250505050565b6000806000838060200190518101906102d5919061180c565b604080516060810182528481526020808201859052818301849052336000908152808252929092208151805196995094975092955093919261031d928492919091019061139b565b506020828101518051610336926001850192019061139b565b506040820151805161035291600284019160209091019061139b565b50506040513391507ff889a5cdc62274389379cbfade0f225b1d30b7395177fd6aeaab61662b1c6edf906102ae908690869086906116f1565b8173ffffffffffffffffffffffffffffffffffffffff8116331480159061043d57506040517f24d7806c00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216906324d7806c90602401602060405180830381865afa158015610417573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043b919061176b565b155b15610474576040517f02bd6bd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526020818152604090912083516104a89285019061139b565b508273ffffffffffffffffffffffffffffffffffffffff167f36195b44a3184513e02477929207751ea9d67026b917ed74d374a7f9e8c5e4d133846040516104f192919061188a565b60405180910390a2505050565b600060208190529081526040902080548190610519906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610545906118b9565b80156105925780601f1061056757610100808354040283529160200191610592565b820191906000526020600020905b81548152906001019060200180831161057557829003601f168201915b5050505050908060010180546105a7906118b9565b80601f01602080910402602001604051908101604052809291908181526020018280546105d3906118b9565b80156106205780601f106105f557610100808354040283529160200191610620565b820191906000526020600020905b81548152906001019060200180831161060357829003601f168201915b505050505090806002018054610635906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610661906118b9565b80156106ae5780601f10610683576101008083540402835291602001916106ae565b820191906000526020600020905b81548152906001019060200180831161069157829003601f168201915b5050505050905083565b3360008181526020819052604080822081516060818101909352815492949392909190829082906106e8906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610714906118b9565b80156107615780601f1061073657610100808354040283529160200191610761565b820191906000526020600020905b81548152906001019060200180831161074457829003601f168201915b5050505050815260200160018201805461077a906118b9565b80601f01602080910402602001604051908101604052809291908181526020018280546107a6906118b9565b80156107f35780601f106107c8576101008083540402835291602001916107f3565b820191906000526020600020905b8154815290600101906020018083116107d657829003601f168201915b5050505050815260200160028201805461080c906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610838906118b9565b80156108855780601f1061085a57610100808354040283529160200191610885565b820191906000526020600020905b81548152906001019060200180831161086857829003601f168201915b5050505050815250509050600082905060008173ffffffffffffffffffffffffffffffffffffffff16633474a4a66040518163ffffffff1660e01b815260040161016060405180830381865afa1580156108e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109079190611925565b6101400151905067ffffffffffffffff811415610922575060005b6109ab8473ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015610970573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261099891908101906119de565b8451602086015160408701518a86610c7b565b9695505050505050565b3360008181526020819052604080822081517f79502c55000000000000000000000000000000000000000000000000000000008152915160609493919284916379502c55916004808201926080929091908290030181865afa158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190611a13565b9050610c738373ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015610a93573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610abb91908101906119de565b83548490610ac8906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610af4906118b9565b8015610b415780601f10610b1657610100808354040283529160200191610b41565b820191906000526020600020905b815481529060010190602001808311610b2457829003601f168201915b5050505050846001018054610b55906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610b81906118b9565b8015610bce5780601f10610ba357610100808354040283529160200191610bce565b820191906000526020600020905b815481529060010190602001808311610bb157829003601f168201915b5050505050856002018054610be2906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610c0e906118b9565b8015610c5b5780601f10610c3057610100808354040283529160200191610c5b565b820191906000526020600020905b815481529060010190602001808311610c3e57829003601f168201915b5050505050856040015161ffff168660600151610cb2565b935050505090565b60606000610c898686610d82565b90506000610c9a8989848888610e12565b9050610ca581610e8e565b9998505050505050505050565b60408051602081019091526000815284516060919015610cef5785604051602001610cdd9190611ab9565b60405160208183030381529060405290505b604080516020810190915260008152855115610d285785604051602001610d169190611afe565b60405160208183030381529060405290505b610ca58989610d3688610ebf565b610d578873ffffffffffffffffffffffffffffffffffffffff166014610ff9565b8686604051602001610d6e96959493929190611b43565b604051602081830303815290604052610e8e565b81518151606091158015911515908290610d995750805b15610dc9578484604051602001610db1929190611c9d565b60405160208183030381529060405292505050610e0c565b8115610de05784604051602001610db19190611d48565b8015610df75783604051602001610db19190611db4565b60405180602001604052806000815250925050505b92915050565b6060808215610e4657610e2483610ebf565b604051602001610e349190611e20565b60405160208183030381529060405290505b86610e5085610ebf565b828888610e5c89610ebf565b8c604051602001610e739796959493929190611e65565b60405160208183030381529060405291505095945050505050565b6060610e9982611247565b604051602001610ea9919061200f565b6040516020818303038152906040529050919050565b606081610eff57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610f295780610f1381612083565b9150610f229050600a836120cd565b9150610f03565b60008167ffffffffffffffff811115610f4457610f44611459565b6040519080825280601f01601f191660200182016040528015610f6e576020820181803683370190505b5090505b8415610ff157610f836001836120e1565b9150610f90600a866120f8565b610f9b90603061210c565b60f81b818381518110610fb057610fb0612124565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610fea600a866120cd565b9450610f72565b949350505050565b60606000611008836002612153565b61101390600261210c565b67ffffffffffffffff81111561102b5761102b611459565b6040519080825280601f01601f191660200182016040528015611055576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061108c5761108c612124565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106110ef576110ef612124565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061112b846002612153565b61113690600161210c565b90505b60018111156111d3577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061117757611177612124565b1a60f81b82828151811061118d5761118d612124565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936111cc81612172565b9050611139565b508315611240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640160405180910390fd5b9392505050565b606081516000141561126757505060408051602081019091526000815290565b600060405180606001604052806040815260200161218a6040913990506000600384516002611296919061210c565b6112a091906120cd565b6112ab906004612153565b67ffffffffffffffff8111156112c3576112c3611459565b6040519080825280601f01601f1916602001820160405280156112ed576020820181803683370190505b509050600182016020820185865187015b80821015611359576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506112fe565b5050600386510660018114611375576002811461138857611390565b603d6001830353603d6002830353611390565b603d60018303535b509195945050505050565b8280546113a7906118b9565b90600052602060002090601f0160209004810192826113c9576000855561140f565b82601f106113e257805160ff191683800117855561140f565b8280016001018555821561140f579182015b8281111561140f5782518255916020019190600101906113f4565b5061141b92915061141f565b5090565b5b8082111561141b5760008155600101611420565b73ffffffffffffffffffffffffffffffffffffffff8116811461145657600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff811182821017156114ac576114ac611459565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156114db576114db611459565b604052919050565b600067ffffffffffffffff8211156114fd576114fd611459565b50601f01601f191660200190565b600061151e611519846114e3565b6114b2565b905082815283838301111561153257600080fd5b828260208301376000602084830101529392505050565b600082601f83011261155a57600080fd5b6112408383356020850161150b565b60008060006060848603121561157e57600080fd5b833561158981611434565b9250602084013567ffffffffffffffff808211156115a657600080fd5b6115b287838801611549565b935060408601359150808211156115c857600080fd5b506115d586828701611549565b9150509250925092565b6000602082840312156115f157600080fd5b813567ffffffffffffffff81111561160857600080fd5b8201601f8101841361161957600080fd5b610ff18482356020840161150b565b6000806040838503121561163b57600080fd5b823561164681611434565b9150602083013567ffffffffffffffff81111561166257600080fd5b61166e85828601611549565b9150509250929050565b60006020828403121561168a57600080fd5b813561124081611434565b60005b838110156116b0578181015183820152602001611698565b838111156116bf576000848401525b50505050565b600081518084526116dd816020860160208601611695565b601f01601f19169290920160200192915050565b60608152600061170460608301866116c5565b828103602084015261171681866116c5565b905082810360408401526109ab81856116c5565b60006020828403121561173c57600080fd5b5035919050565b60208152600061124060208301846116c5565b8051801515811461176657600080fd5b919050565b60006020828403121561177d57600080fd5b61124082611756565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006117b560608301856116c5565b82810360408401526109ab81856116c5565b600082601f8301126117d857600080fd5b81516117e6611519826114e3565b8181528460208386010111156117fb57600080fd5b610ff1826020830160208701611695565b60008060006060848603121561182157600080fd5b835167ffffffffffffffff8082111561183957600080fd5b611845878388016117c7565b9450602086015191508082111561185b57600080fd5b611867878388016117c7565b9350604086015191508082111561187d57600080fd5b506115d5868287016117c7565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201526000610ff160408301846116c5565b600181811c908216806118cd57607f821691505b60208210811415611907577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b805167ffffffffffffffff8116811461176657600080fd5b6000610160828403121561193857600080fd5b611940611488565b61194983611756565b815261195760208401611756565b6020820152604083015160408201526119726060840161190d565b60608201526119836080840161190d565b608082015261199460a0840161190d565b60a08201526119a560c0840161190d565b60c082015260e0838101519082015261010080840151908201526101208084015190820152610140928301519281019290925250919050565b6000602082840312156119f057600080fd5b815167ffffffffffffffff811115611a0757600080fd5b610ff1848285016117c7565b600060808284031215611a2557600080fd5b6040516080810181811067ffffffffffffffff82111715611a4857611a48611459565b6040528251611a5681611434565b8152611a646020840161190d565b6020820152604083015161ffff81168114611a7e57600080fd5b60408201526060830151611a9181611434565b60608201529392505050565b60008151611aaf818560208601611695565b9290920192915050565b7f222c2022696d616765223a202200000000000000000000000000000000000000815260008251611af181600d850160208701611695565b91909101600d0192915050565b7f222c2022616e696d6174696f6e5f75726c223a20220000000000000000000000815260008251611b36816015850160208701611695565b9190910160150192915050565b7f7b226e616d65223a2022000000000000000000000000000000000000000000008152600087516020611b7c82600a8601838d01611695565b7f222c20226465736372697074696f6e223a202200000000000000000000000000600a928501928301528851611bb881601d8501848d01611695565b7f222c202273656c6c65725f6665655f62617369735f706f696e7473223a200000601d93909101928301528751611bf581603b8501848c01611695565b7f2c20226665655f726563697069656e74223a2022000000000000000000000000603b93909101928301528651611c3281604f8501848b01611695565b8651920191611c4781604f8501848a01611695565b8551920191611c5c81604f8501848901611695565b611c8e604f828501017f227d000000000000000000000000000000000000000000000000000000000000815260020190565b9b9a5050505050505050505050565b7f696d616765223a20220000000000000000000000000000000000000000000000815260008351611cd5816009850160208801611695565b7f222c2022616e696d6174696f6e5f75726c223a202200000000000000000000006009918401918201528351611d1281601e840160208801611695565b7f222c202200000000000000000000000000000000000000000000000000000000601e9290910191820152602201949350505050565b7f696d616765223a20220000000000000000000000000000000000000000000000815260008251611d80816009850160208701611695565b7f222c2022000000000000000000000000000000000000000000000000000000006009939091019283015250600d01919050565b7f616e696d6174696f6e5f75726c223a2022000000000000000000000000000000815260008251611dec816011850160208701611695565b7f222c2022000000000000000000000000000000000000000000000000000000006011939091019283015250601501919050565b7f2f00000000000000000000000000000000000000000000000000000000000000815260008251611e58816001850160208701611695565b9190910160010192915050565b7f7b226e616d65223a202200000000000000000000000000000000000000000000815260008851611e9d81600a850160208d01611695565b7f2000000000000000000000000000000000000000000000000000000000000000600a918401918201528851611eda81600b840160208d01611695565b8851910190611ef081600b840160208c01611695565b8082019150507f222c20220000000000000000000000000000000000000000000000000000000080600b8301527f6465736372697074696f6e223a20220000000000000000000000000000000000600f8301528751611f5681601e850160208c01611695565b601e920191820152612001611fd8611fd2611fa9611fa3611f7a602287018c611a9d565b7f70726f70657274696573223a207b226e756d626572223a200000000000000000815260180190565b89611a9d565b7f2c20226e616d65223a20220000000000000000000000000000000000000000008152600b0190565b86611a9d565b7f227d7d0000000000000000000000000000000000000000000000000000000000815260030190565b9a9950505050505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161204781601d850160208701611695565b91909101601d0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600060001982141561209757612097612054565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826120dc576120dc61209e565b500490565b6000828210156120f3576120f3612054565b500390565b6000826121075761210761209e565b500690565b6000821982111561211f5761211f612054565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081600019048311821515161561216d5761216d612054565b500290565b60008161218157612181612054565b50600019019056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220b6232ae97b670c8878db7f728f3de0526613265d63b35bcb7f66c39cbb2de89b64736f6c634300080a0033

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063ba46ae7211610050578063ba46ae72146100b2578063c87b56dd146100dd578063e8a3d485146100fd57600080fd5b80632f17b8f014610077578063856a7ffa1461008c5780638bbb2cf21461009f575b600080fd5b61008a610085366004611569565b610105565b005b61008a61009a3660046115df565b6102bc565b61008a6100ad366004611628565b61038b565b6100c56100c0366004611678565b6104fe565b6040516100d4939291906116f1565b60405180910390f35b6100f06100eb36600461172a565b6106b8565b6040516100d49190611743565b6100f06109b5565b8273ffffffffffffffffffffffffffffffffffffffff811633148015906101b757506040517f24d7806c00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216906324d7806c90602401602060405180830381865afa158015610191573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101b5919061176b565b155b156101ee576040517f02bd6bd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526020818152604090912084516102289260019092019186019061139b565b5073ffffffffffffffffffffffffffffffffffffffff841660009081526020818152604090912083516102639260029092019185019061139b565b508373ffffffffffffffffffffffffffffffffffffffff167fc4c1b9223fcebe5f35b9030d3df655018c40e88d70b8a3c63ed851c5d972210f3385856040516102ae93929190611786565b60405180910390a250505050565b6000806000838060200190518101906102d5919061180c565b604080516060810182528481526020808201859052818301849052336000908152808252929092208151805196995094975092955093919261031d928492919091019061139b565b506020828101518051610336926001850192019061139b565b506040820151805161035291600284019160209091019061139b565b50506040513391507ff889a5cdc62274389379cbfade0f225b1d30b7395177fd6aeaab61662b1c6edf906102ae908690869086906116f1565b8173ffffffffffffffffffffffffffffffffffffffff8116331480159061043d57506040517f24d7806c00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216906324d7806c90602401602060405180830381865afa158015610417573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043b919061176b565b155b15610474576040517f02bd6bd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526020818152604090912083516104a89285019061139b565b508273ffffffffffffffffffffffffffffffffffffffff167f36195b44a3184513e02477929207751ea9d67026b917ed74d374a7f9e8c5e4d133846040516104f192919061188a565b60405180910390a2505050565b600060208190529081526040902080548190610519906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610545906118b9565b80156105925780601f1061056757610100808354040283529160200191610592565b820191906000526020600020905b81548152906001019060200180831161057557829003601f168201915b5050505050908060010180546105a7906118b9565b80601f01602080910402602001604051908101604052809291908181526020018280546105d3906118b9565b80156106205780601f106105f557610100808354040283529160200191610620565b820191906000526020600020905b81548152906001019060200180831161060357829003601f168201915b505050505090806002018054610635906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610661906118b9565b80156106ae5780601f10610683576101008083540402835291602001916106ae565b820191906000526020600020905b81548152906001019060200180831161069157829003601f168201915b5050505050905083565b3360008181526020819052604080822081516060818101909352815492949392909190829082906106e8906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610714906118b9565b80156107615780601f1061073657610100808354040283529160200191610761565b820191906000526020600020905b81548152906001019060200180831161074457829003601f168201915b5050505050815260200160018201805461077a906118b9565b80601f01602080910402602001604051908101604052809291908181526020018280546107a6906118b9565b80156107f35780601f106107c8576101008083540402835291602001916107f3565b820191906000526020600020905b8154815290600101906020018083116107d657829003601f168201915b5050505050815260200160028201805461080c906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610838906118b9565b80156108855780601f1061085a57610100808354040283529160200191610885565b820191906000526020600020905b81548152906001019060200180831161086857829003601f168201915b5050505050815250509050600082905060008173ffffffffffffffffffffffffffffffffffffffff16633474a4a66040518163ffffffff1660e01b815260040161016060405180830381865afa1580156108e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109079190611925565b6101400151905067ffffffffffffffff811415610922575060005b6109ab8473ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015610970573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261099891908101906119de565b8451602086015160408701518a86610c7b565b9695505050505050565b3360008181526020819052604080822081517f79502c55000000000000000000000000000000000000000000000000000000008152915160609493919284916379502c55916004808201926080929091908290030181865afa158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190611a13565b9050610c738373ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015610a93573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610abb91908101906119de565b83548490610ac8906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610af4906118b9565b8015610b415780601f10610b1657610100808354040283529160200191610b41565b820191906000526020600020905b815481529060010190602001808311610b2457829003601f168201915b5050505050846001018054610b55906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610b81906118b9565b8015610bce5780601f10610ba357610100808354040283529160200191610bce565b820191906000526020600020905b815481529060010190602001808311610bb157829003601f168201915b5050505050856002018054610be2906118b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610c0e906118b9565b8015610c5b5780601f10610c3057610100808354040283529160200191610c5b565b820191906000526020600020905b815481529060010190602001808311610c3e57829003601f168201915b5050505050856040015161ffff168660600151610cb2565b935050505090565b60606000610c898686610d82565b90506000610c9a8989848888610e12565b9050610ca581610e8e565b9998505050505050505050565b60408051602081019091526000815284516060919015610cef5785604051602001610cdd9190611ab9565b60405160208183030381529060405290505b604080516020810190915260008152855115610d285785604051602001610d169190611afe565b60405160208183030381529060405290505b610ca58989610d3688610ebf565b610d578873ffffffffffffffffffffffffffffffffffffffff166014610ff9565b8686604051602001610d6e96959493929190611b43565b604051602081830303815290604052610e8e565b81518151606091158015911515908290610d995750805b15610dc9578484604051602001610db1929190611c9d565b60405160208183030381529060405292505050610e0c565b8115610de05784604051602001610db19190611d48565b8015610df75783604051602001610db19190611db4565b60405180602001604052806000815250925050505b92915050565b6060808215610e4657610e2483610ebf565b604051602001610e349190611e20565b60405160208183030381529060405290505b86610e5085610ebf565b828888610e5c89610ebf565b8c604051602001610e739796959493929190611e65565b60405160208183030381529060405291505095945050505050565b6060610e9982611247565b604051602001610ea9919061200f565b6040516020818303038152906040529050919050565b606081610eff57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610f295780610f1381612083565b9150610f229050600a836120cd565b9150610f03565b60008167ffffffffffffffff811115610f4457610f44611459565b6040519080825280601f01601f191660200182016040528015610f6e576020820181803683370190505b5090505b8415610ff157610f836001836120e1565b9150610f90600a866120f8565b610f9b90603061210c565b60f81b818381518110610fb057610fb0612124565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610fea600a866120cd565b9450610f72565b949350505050565b60606000611008836002612153565b61101390600261210c565b67ffffffffffffffff81111561102b5761102b611459565b6040519080825280601f01601f191660200182016040528015611055576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061108c5761108c612124565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106110ef576110ef612124565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061112b846002612153565b61113690600161210c565b90505b60018111156111d3577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061117757611177612124565b1a60f81b82828151811061118d5761118d612124565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936111cc81612172565b9050611139565b508315611240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640160405180910390fd5b9392505050565b606081516000141561126757505060408051602081019091526000815290565b600060405180606001604052806040815260200161218a6040913990506000600384516002611296919061210c565b6112a091906120cd565b6112ab906004612153565b67ffffffffffffffff8111156112c3576112c3611459565b6040519080825280601f01601f1916602001820160405280156112ed576020820181803683370190505b509050600182016020820185865187015b80821015611359576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506112fe565b5050600386510660018114611375576002811461138857611390565b603d6001830353603d6002830353611390565b603d60018303535b509195945050505050565b8280546113a7906118b9565b90600052602060002090601f0160209004810192826113c9576000855561140f565b82601f106113e257805160ff191683800117855561140f565b8280016001018555821561140f579182015b8281111561140f5782518255916020019190600101906113f4565b5061141b92915061141f565b5090565b5b8082111561141b5760008155600101611420565b73ffffffffffffffffffffffffffffffffffffffff8116811461145657600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff811182821017156114ac576114ac611459565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156114db576114db611459565b604052919050565b600067ffffffffffffffff8211156114fd576114fd611459565b50601f01601f191660200190565b600061151e611519846114e3565b6114b2565b905082815283838301111561153257600080fd5b828260208301376000602084830101529392505050565b600082601f83011261155a57600080fd5b6112408383356020850161150b565b60008060006060848603121561157e57600080fd5b833561158981611434565b9250602084013567ffffffffffffffff808211156115a657600080fd5b6115b287838801611549565b935060408601359150808211156115c857600080fd5b506115d586828701611549565b9150509250925092565b6000602082840312156115f157600080fd5b813567ffffffffffffffff81111561160857600080fd5b8201601f8101841361161957600080fd5b610ff18482356020840161150b565b6000806040838503121561163b57600080fd5b823561164681611434565b9150602083013567ffffffffffffffff81111561166257600080fd5b61166e85828601611549565b9150509250929050565b60006020828403121561168a57600080fd5b813561124081611434565b60005b838110156116b0578181015183820152602001611698565b838111156116bf576000848401525b50505050565b600081518084526116dd816020860160208601611695565b601f01601f19169290920160200192915050565b60608152600061170460608301866116c5565b828103602084015261171681866116c5565b905082810360408401526109ab81856116c5565b60006020828403121561173c57600080fd5b5035919050565b60208152600061124060208301846116c5565b8051801515811461176657600080fd5b919050565b60006020828403121561177d57600080fd5b61124082611756565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006117b560608301856116c5565b82810360408401526109ab81856116c5565b600082601f8301126117d857600080fd5b81516117e6611519826114e3565b8181528460208386010111156117fb57600080fd5b610ff1826020830160208701611695565b60008060006060848603121561182157600080fd5b835167ffffffffffffffff8082111561183957600080fd5b611845878388016117c7565b9450602086015191508082111561185b57600080fd5b611867878388016117c7565b9350604086015191508082111561187d57600080fd5b506115d5868287016117c7565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201526000610ff160408301846116c5565b600181811c908216806118cd57607f821691505b60208210811415611907577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b805167ffffffffffffffff8116811461176657600080fd5b6000610160828403121561193857600080fd5b611940611488565b61194983611756565b815261195760208401611756565b6020820152604083015160408201526119726060840161190d565b60608201526119836080840161190d565b608082015261199460a0840161190d565b60a08201526119a560c0840161190d565b60c082015260e0838101519082015261010080840151908201526101208084015190820152610140928301519281019290925250919050565b6000602082840312156119f057600080fd5b815167ffffffffffffffff811115611a0757600080fd5b610ff1848285016117c7565b600060808284031215611a2557600080fd5b6040516080810181811067ffffffffffffffff82111715611a4857611a48611459565b6040528251611a5681611434565b8152611a646020840161190d565b6020820152604083015161ffff81168114611a7e57600080fd5b60408201526060830151611a9181611434565b60608201529392505050565b60008151611aaf818560208601611695565b9290920192915050565b7f222c2022696d616765223a202200000000000000000000000000000000000000815260008251611af181600d850160208701611695565b91909101600d0192915050565b7f222c2022616e696d6174696f6e5f75726c223a20220000000000000000000000815260008251611b36816015850160208701611695565b9190910160150192915050565b7f7b226e616d65223a2022000000000000000000000000000000000000000000008152600087516020611b7c82600a8601838d01611695565b7f222c20226465736372697074696f6e223a202200000000000000000000000000600a928501928301528851611bb881601d8501848d01611695565b7f222c202273656c6c65725f6665655f62617369735f706f696e7473223a200000601d93909101928301528751611bf581603b8501848c01611695565b7f2c20226665655f726563697069656e74223a2022000000000000000000000000603b93909101928301528651611c3281604f8501848b01611695565b8651920191611c4781604f8501848a01611695565b8551920191611c5c81604f8501848901611695565b611c8e604f828501017f227d000000000000000000000000000000000000000000000000000000000000815260020190565b9b9a5050505050505050505050565b7f696d616765223a20220000000000000000000000000000000000000000000000815260008351611cd5816009850160208801611695565b7f222c2022616e696d6174696f6e5f75726c223a202200000000000000000000006009918401918201528351611d1281601e840160208801611695565b7f222c202200000000000000000000000000000000000000000000000000000000601e9290910191820152602201949350505050565b7f696d616765223a20220000000000000000000000000000000000000000000000815260008251611d80816009850160208701611695565b7f222c2022000000000000000000000000000000000000000000000000000000006009939091019283015250600d01919050565b7f616e696d6174696f6e5f75726c223a2022000000000000000000000000000000815260008251611dec816011850160208701611695565b7f222c2022000000000000000000000000000000000000000000000000000000006011939091019283015250601501919050565b7f2f00000000000000000000000000000000000000000000000000000000000000815260008251611e58816001850160208701611695565b9190910160010192915050565b7f7b226e616d65223a202200000000000000000000000000000000000000000000815260008851611e9d81600a850160208d01611695565b7f2000000000000000000000000000000000000000000000000000000000000000600a918401918201528851611eda81600b840160208d01611695565b8851910190611ef081600b840160208c01611695565b8082019150507f222c20220000000000000000000000000000000000000000000000000000000080600b8301527f6465736372697074696f6e223a20220000000000000000000000000000000000600f8301528751611f5681601e850160208c01611695565b601e920191820152612001611fd8611fd2611fa9611fa3611f7a602287018c611a9d565b7f70726f70657274696573223a207b226e756d626572223a200000000000000000815260180190565b89611a9d565b7f2c20226e616d65223a20220000000000000000000000000000000000000000008152600b0190565b86611a9d565b7f227d7d0000000000000000000000000000000000000000000000000000000000815260030190565b9a9950505050505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161204781601d850160208701611695565b91909101601d0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600060001982141561209757612097612054565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826120dc576120dc61209e565b500490565b6000828210156120f3576120f3612054565b500390565b6000826121075761210761209e565b500690565b6000821982111561211f5761211f612054565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081600019048311821515161561216d5761216d612054565b500290565b60008161218157612181612054565b50600019019056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220b6232ae97b670c8878db7f728f3de0526613265d63b35bcb7f66c39cbb2de89b64736f6c634300080a0033