Feature Tip: Add private address tag to any address under My Name Tag !
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
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x6101c034 | 16844200 | 489 days ago | IN | Create: ZoraCreator1155Impl | 0 ETH | 0.10679919 |
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 Name:
ZoraCreator1155Impl
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 5000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {ERC1155Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; import {IERC1155MetadataURIUpgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC1155MetadataURIUpgradeable.sol"; import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol"; import {IZoraCreator1155} from "../interfaces/IZoraCreator1155.sol"; import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {ContractVersionBase} from "../version/ContractVersionBase.sol"; import {CreatorPermissionControl} from "../permissions/CreatorPermissionControl.sol"; import {CreatorRendererControl} from "../renderer/CreatorRendererControl.sol"; import {CreatorRoyaltiesControl} from "../royalties/CreatorRoyaltiesControl.sol"; import {ICreatorCommands} from "../interfaces/ICreatorCommands.sol"; import {IMinter1155} from "../interfaces/IMinter1155.sol"; import {IRenderer1155} from "../interfaces/IRenderer1155.sol"; import {ITransferHookReceiver} from "../interfaces/ITransferHookReceiver.sol"; import {IZoraCreator1155} from "../interfaces/IZoraCreator1155.sol"; import {LegacyNamingControl} from "../legacy-naming/LegacyNamingControl.sol"; import {MintFeeManager} from "../fee/MintFeeManager.sol"; import {PublicMulticall} from "../utils/PublicMulticall.sol"; import {SharedBaseConstants} from "../shared/SharedBaseConstants.sol"; import {TransferHelperUtils} from "../utils/TransferHelperUtils.sol"; import {ZoraCreator1155StorageV1} from "./ZoraCreator1155StorageV1.sol"; /// Imagine. Mint. Enjoy. /// @title ZoraCreator1155Impl /// @notice The core implementation contract for a creator's 1155 token /// @author @iainnash / @tbtstl contract ZoraCreator1155Impl is IZoraCreator1155, ContractVersionBase, ReentrancyGuardUpgradeable, PublicMulticall, ERC1155Upgradeable, MintFeeManager, UUPSUpgradeable, CreatorRendererControl, LegacyNamingControl, ZoraCreator1155StorageV1, CreatorPermissionControl, CreatorRoyaltiesControl { /// @notice This user role allows for any action to be performed uint256 public immutable PERMISSION_BIT_ADMIN = 2 ** 1; /// @notice This user role allows for only mint actions to be performed uint256 public immutable PERMISSION_BIT_MINTER = 2 ** 2; /// @notice This user role allows for only managing sales configurations uint256 public immutable PERMISSION_BIT_SALES = 2 ** 3; /// @notice This user role allows for only managing metadata configuration uint256 public immutable PERMISSION_BIT_METADATA = 2 ** 4; /// @notice This user role allows for only withdrawing funds and setting funds withdraw address uint256 public immutable PERMISSION_BIT_FUNDS_MANAGER = 2 ** 5; constructor(uint256 _mintFeeAmount, address _mintFeeRecipient) MintFeeManager(_mintFeeAmount, _mintFeeRecipient) initializer {} /// @notice Initializes the contract /// @param newContractURI The contract URI /// @param defaultRoyaltyConfiguration The default royalty configuration /// @param defaultAdmin The default admin to manage the token /// @param setupActions The setup actions to run, if any function initialize( string memory newContractURI, RoyaltyConfiguration memory defaultRoyaltyConfiguration, address payable defaultAdmin, bytes[] calldata setupActions ) external nonReentrant initializer { // We are not initalizing the OZ 1155 implementation // to save contract storage space and runtime // since the only thing affected here is the uri. // __ERC1155_init(""); // Setup uups __UUPSUpgradeable_init(); // Setup re-entracy guard __ReentrancyGuard_init(); // Setup contract-default token ID _setupDefaultToken(defaultAdmin, newContractURI, defaultRoyaltyConfiguration); // Set owner to default admin _setOwner(defaultAdmin); _setFundsRecipient(defaultAdmin); // Run Setup actions if (setupActions.length > 0) { // Temporarily make sender admin _addPermission(CONTRACT_BASE_ID, msg.sender, PERMISSION_BIT_ADMIN); // Make calls multicall(setupActions); // Remove admin _removePermission(CONTRACT_BASE_ID, msg.sender, PERMISSION_BIT_ADMIN); } } /// @notice sets up the global configuration for the 1155 contract /// @param newContractURI The contract URI /// @param defaultRoyaltyConfiguration The default royalty configuration function _setupDefaultToken(address defaultAdmin, string memory newContractURI, RoyaltyConfiguration memory defaultRoyaltyConfiguration) internal { // Add admin permission to default admin to manage contract _addPermission(CONTRACT_BASE_ID, defaultAdmin, PERMISSION_BIT_ADMIN); // Mint token ID 0 / don't allow any user mints _setupNewToken(newContractURI, 0); // Update default royalties _updateRoyalties(CONTRACT_BASE_ID, defaultRoyaltyConfiguration); } /// @notice Updates the royalty configuration for a token /// @param tokenId The token ID to update /// @param newConfiguration The new royalty configuration function updateRoyaltiesForToken( uint256 tokenId, RoyaltyConfiguration memory newConfiguration ) external onlyAdminOrRole(tokenId, PERMISSION_BIT_FUNDS_MANAGER) { _updateRoyalties(tokenId, newConfiguration); } /// @notice remove this function from openzeppelin impl /// @dev This makes this internal function a no-op function _setURI(string memory newuri) internal virtual override {} /// @notice This gets the next token in line to be minted when minting linearly (default behavior) and updates the counter function _getAndUpdateNextTokenId() internal returns (uint256) { unchecked { return nextTokenId++; } } /// @notice Ensure that the next token ID is correct /// @dev This reverts if the invariant doesn't match. This is used for multicall token id assumptions /// @param lastTokenId The last token ID function assumeLastTokenIdMatches(uint256 lastTokenId) external view { unchecked { if (nextTokenId - 1 != lastTokenId) { revert TokenIdMismatch(lastTokenId, nextTokenId - 1); } } } /// @notice Checks if a user either has a role for a token or if they are the admin /// @dev This is an internal function that is called by the external getter and internal functions /// @param user The user to check /// @param tokenId The token ID to check /// @param role The role to check /// @return true or false if the permission exists for the user given the token id function _isAdminOrRole(address user, uint256 tokenId, uint256 role) internal view returns (bool) { return _hasAnyPermission(tokenId, user, PERMISSION_BIT_ADMIN | role); } /// @notice Checks if a user either has a role for a token or if they are the admin /// @param user The user to check /// @param tokenId The token ID to check /// @param role The role to check /// @return true or false if the permission exists for the user given the token id function isAdminOrRole(address user, uint256 tokenId, uint256 role) external view returns (bool) { return _isAdminOrRole(user, tokenId, role); } /// @notice Checks if the user is an admin for the given tokenId /// @dev This function reverts if the permission does not exist for the given user and tokenId /// @param user user to check /// @param tokenId tokenId to check /// @param role role to check for admin function _requireAdminOrRole(address user, uint256 tokenId, uint256 role) internal view { if (!(_hasAnyPermission(tokenId, user, PERMISSION_BIT_ADMIN | role) || _hasAnyPermission(CONTRACT_BASE_ID, user, PERMISSION_BIT_ADMIN))) { revert UserMissingRoleForToken(user, tokenId, role); } } /// @notice Checks if the user is an admin /// @dev This reverts if the user is not an admin for the given token id or contract /// @param user user to check /// @param tokenId tokenId to check function _requireAdmin(address user, uint256 tokenId) internal view { if (!(_hasAnyPermission(tokenId, user, PERMISSION_BIT_ADMIN) || _hasAnyPermission(CONTRACT_BASE_ID, user, PERMISSION_BIT_ADMIN))) { revert UserMissingRoleForToken(user, tokenId, PERMISSION_BIT_ADMIN); } } /// @notice Modifier checking if the user is an admin or has a role /// @dev This reverts if the msg.sender is not an admin for the given token id or contract /// @param tokenId tokenId to check /// @param role role to check modifier onlyAdminOrRole(uint256 tokenId, uint256 role) { _requireAdminOrRole(msg.sender, tokenId, role); _; } /// @notice Modifier checking if the user is an admin /// @dev This reverts if the msg.sender is not an admin for the given token id or contract /// @param tokenId tokenId to check modifier onlyAdmin(uint256 tokenId) { _requireAdmin(msg.sender, tokenId); _; } /// @notice Modifier checking if the requested quantity of tokens can be minted for the tokenId /// @dev This reverts if the number that can be minted is exceeded /// @param tokenId token id to check available allowed quantity /// @param quantity requested to be minted modifier canMintQuantity(uint256 tokenId, uint256 quantity) { _requireCanMintQuantity(tokenId, quantity); _; } /// @notice Only from approved address for burn /// @param from address that the tokens will be burned from, validate that this is msg.sender or that msg.sender is approved modifier onlyFromApprovedForBurn(address from) { if (from != msg.sender && !isApprovedForAll(from, msg.sender)) { revert Burn_NotOwnerOrApproved(msg.sender, from); } _; } /// @notice Checks if a user can mint a quantity of a token /// @dev Reverts if the mint exceeds the allowed quantity (or if the token does not exist) /// @param tokenId The token ID to check /// @param quantity The quantity of tokens to mint to check function _requireCanMintQuantity(uint256 tokenId, uint256 quantity) internal view { TokenData memory tokenInformation = tokens[tokenId]; if (tokenInformation.totalMinted + quantity > tokenInformation.maxSupply) { revert CannotMintMoreTokens(tokenId, quantity, tokenInformation.totalMinted, tokenInformation.maxSupply); } } /// @notice Set up a new token /// @param newURI The URI for the token (underscore since `uri()` is reserved by OpenZeppelin) /// @param maxSupply The maximum supply of the token function setupNewToken( string memory newURI, uint256 maxSupply ) public onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_MINTER) nonReentrant returns (uint256) { // TODO(iain): isMaxSupply = 0 open edition or maybe uint256(max) - 1 // 0xffffffff -> 2**8*4 4.2bil // 0xf0000000 -> 2**8*4-(8*3) uint256 tokenId = _setupNewToken(newURI, maxSupply); // Allow the token creator to administrate this token _addPermission(tokenId, msg.sender, PERMISSION_BIT_ADMIN); if (bytes(newURI).length > 0) { emit URI(newURI, tokenId); } emit SetupNewToken(tokenId, msg.sender, newURI, maxSupply); return tokenId; } /// @notice Update the token URI for a token /// @param tokenId The token ID to update the URI for /// @param _newURI The new URI function updateTokenURI(uint256 tokenId, string memory _newURI) external onlyAdminOrRole(tokenId, PERMISSION_BIT_METADATA) { if (tokenId == CONTRACT_BASE_ID) { revert NotAllowedContractBaseIDUpdate(); } emit URI(_newURI, tokenId); tokens[tokenId].uri = _newURI; } /// @notice Update the global contract metadata /// @param _newURI The new contract URI /// @param _newName The new contract name function updateContractMetadata(string memory _newURI, string memory _newName) external onlyAdminOrRole(0, PERMISSION_BIT_METADATA) { tokens[CONTRACT_BASE_ID].uri = _newURI; _setName(_newName); emit ContractMetadataUpdated(msg.sender, _newURI, _newName); } function _setupNewToken(string memory newURI, uint256 maxSupply) internal returns (uint256 tokenId) { tokenId = _getAndUpdateNextTokenId(); TokenData memory tokenData = TokenData({uri: newURI, maxSupply: maxSupply, totalMinted: 0}); tokens[tokenId] = tokenData; emit UpdatedToken(msg.sender, tokenId, tokenData); } /// @notice Add a role to a user for a token /// @param tokenId The token ID to add the role to /// @param user The user to add the role to /// @param permissionBits The permission bit to add function addPermission(uint256 tokenId, address user, uint256 permissionBits) external onlyAdmin(tokenId) { _addPermission(tokenId, user, permissionBits); } /// @notice Remove a role from a user for a token /// @param tokenId The token ID to remove the role from /// @param user The user to remove the role from /// @param permissionBits The permission bit to remove function removePermission(uint256 tokenId, address user, uint256 permissionBits) external onlyAdmin(tokenId) { _removePermission(tokenId, user, permissionBits); // Clear owner field if (tokenId == CONTRACT_BASE_ID && user == config.owner && !_hasAnyPermission(CONTRACT_BASE_ID, user, PERMISSION_BIT_ADMIN)) { _setOwner(address(0)); } } /// @notice Set the owner of the contract /// @param newOwner The new owner of the contract function setOwner(address newOwner) external onlyAdmin(CONTRACT_BASE_ID) { if (!_hasAnyPermission(CONTRACT_BASE_ID, newOwner, PERMISSION_BIT_ADMIN)) { revert NewOwnerNeedsToBeAdmin(); } // Update owner field _setOwner(newOwner); } /// @notice Getter for the owner singleton of the contract for outside interfaces /// @return the owner of the contract singleton for compat. function owner() external view returns (address) { return config.owner; } /// @notice AdminMint that only checks if the requested quantity can be minted and has a re-entrant guard /// @param recipient recipient for admin minted tokens /// @param tokenId token id to mint /// @param quantity quantity to mint /// @param data callback data as specified by the 1155 spec function _adminMint(address recipient, uint256 tokenId, uint256 quantity, bytes memory data) internal { _mint(recipient, tokenId, quantity, data); } /// @notice Mint a token to a user as the admin or minter /// @param recipient The recipient of the token /// @param tokenId The token ID to mint /// @param quantity The quantity of tokens to mint /// @param data The data to pass to the onERC1155Received function function adminMint( address recipient, uint256 tokenId, uint256 quantity, bytes memory data ) external nonReentrant onlyAdminOrRole(tokenId, PERMISSION_BIT_MINTER) { // Call internal admin mint _adminMint(recipient, tokenId, quantity, data); } /// @notice Batch mint tokens to a user as the admin or minter /// @param recipient The recipient of the tokens /// @param tokenIds The token IDs to mint /// @param quantities The quantities of tokens to mint /// @param data The data to pass to the onERC1155BatchReceived function function adminMintBatch(address recipient, uint256[] memory tokenIds, uint256[] memory quantities, bytes memory data) external nonReentrant { bool isGlobalAdminOrMinter = _isAdminOrRole(msg.sender, CONTRACT_BASE_ID, PERMISSION_BIT_MINTER); for (uint256 i = 0; i < tokenIds.length; ++i) { if (!isGlobalAdminOrMinter) { _requireAdminOrRole(msg.sender, tokenIds[i], PERMISSION_BIT_MINTER); } } _mintBatch(recipient, tokenIds, quantities, data); } /// @notice Mint tokens given a minter contract and minter arguments /// @param minter The minter contract to use /// @param tokenId The token ID to mint /// @param quantity The quantity of tokens to mint /// @param minterArguments The arguments to pass to the minter function mint(IMinter1155 minter, uint256 tokenId, uint256 quantity, bytes calldata minterArguments) external payable nonReentrant { // Require admin from the minter to mint _requireAdminOrRole(address(minter), tokenId, PERMISSION_BIT_MINTER); // Get value sent and handle mint fee uint256 ethValueSent = _handleFeeAndGetValueSent(quantity); // Execute commands returned from minter _executeCommands(minter.requestMint(address(this), tokenId, quantity, ethValueSent, minterArguments).commands, ethValueSent, tokenId); emit Purchased(msg.sender, address(minter), tokenId, quantity, msg.value); } /// @notice Set a metadata renderer for a token /// @param tokenId The token ID to set the renderer for /// @param renderer The renderer to set /// @param setupData The data to pass to the renderer upon intialization function setTokenMetadataRenderer( uint256 tokenId, IRenderer1155 renderer, bytes calldata setupData ) external nonReentrant onlyAdminOrRole(tokenId, PERMISSION_BIT_METADATA) { _setRenderer(tokenId, renderer, setupData); if (tokenId == 0) { emit ContractRendererUpdated(renderer); } else { // We don't know the uri from the renderer but can emit a notification to the indexer here emit URI("", tokenId); } } /// Execute Minter Commands /// /// @notice Internal functions to execute commands returned by the minter /// @param commands list of command structs /// @param ethValueSent the ethereum value sent in the mint transaction into the contract /// @param tokenId the token id the user requested to mint (0 if the token id is set by the minter itself across the whole contract) function _executeCommands(ICreatorCommands.Command[] memory commands, uint256 ethValueSent, uint256 tokenId) internal { for (uint256 i = 0; i < commands.length; ++i) { ICreatorCommands.CreatorActions method = commands[i].method; if (method == ICreatorCommands.CreatorActions.SEND_ETH) { (address recipient, uint256 amount) = abi.decode(commands[i].args, (address, uint256)); if (ethValueSent > amount) { revert Mint_InsolventSaleTransfer(); } if (!TransferHelperUtils.safeSendETH(recipient, amount)) { revert Mint_ValueTransferFail(); } } else if (method == ICreatorCommands.CreatorActions.MINT) { (address recipient, uint256 mintTokenId, uint256 quantity) = abi.decode(commands[i].args, (address, uint256, uint256)); if (tokenId != 0 && mintTokenId != tokenId) { revert Mint_TokenIDMintNotAllowed(); } _adminMint(recipient, tokenId, quantity, ""); } else if (method == ICreatorCommands.CreatorActions.NO_OP) { // no-op } else { revert Mint_UnknownCommand(); } } } /// @notice Token info getter /// @param tokenId token id to get info for /// @return TokenData struct returned function getTokenInfo(uint256 tokenId) external view returns (TokenData memory) { return tokens[tokenId]; } /// @notice Proxy setter for sale contracts (only callable by SALES permission or admin) /// @param tokenId The token ID to call the sale contract with /// @param salesConfig The sales config contract to call /// @param data The data to pass to the sales config contract function callSale(uint256 tokenId, IMinter1155 salesConfig, bytes memory data) external onlyAdminOrRole(tokenId, PERMISSION_BIT_SALES) { _requireAdminOrRole(address(salesConfig), tokenId, PERMISSION_BIT_MINTER); if (!salesConfig.supportsInterface(type(IMinter1155).interfaceId)) { revert Sale_CannotCallNonSalesContract(address(salesConfig)); } (bool success, ) = address(salesConfig).call(data); if (!success) { revert Sale_CallFailed(); } } /// @notice Proxy setter for renderer contracts (only callable by METADATA permission or admin) /// @param tokenId The token ID to call the renderer contract with /// @param data The data to pass to the renderer contract function callRenderer(uint256 tokenId, bytes memory data) external onlyAdminOrRole(tokenId, PERMISSION_BIT_METADATA) { // We assume any renderers set are checked for EIP165 signature during write stage. (bool success, bytes memory why) = address(getCustomRenderer(tokenId)).call(data); if (!success) { revert Renderer_CallFailed(why); } } /// @notice Returns true if the contract implements the interface defined by interfaceId /// @param interfaceId The interface to check for /// @return if the interfaceId is marked as supported function supportsInterface( bytes4 interfaceId ) public view virtual override(CreatorRoyaltiesControl, ERC1155Upgradeable, IERC165Upgradeable) returns (bool) { return super.supportsInterface(interfaceId) || interfaceId == type(IZoraCreator1155).interfaceId; } /// Generic 1155 function overrides /// /// @notice Mint function that 1) checks quantity and 2) handles supply royalty 3) keeps track of allowed tokens /// @param to to mint to /// @param id token id to mint /// @param amount of tokens to mint /// @param data as specified by 1155 standard function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal virtual override { (address supplyRoyaltyRecipient, uint256 supplyRoyaltyAmount) = supplyRoyaltyInfo(id, tokens[id].totalMinted, amount); _requireCanMintQuantity(id, amount + supplyRoyaltyAmount); super._mint(to, id, amount, data); if (supplyRoyaltyAmount > 0) { super._mint(supplyRoyaltyRecipient, id, supplyRoyaltyAmount, data); } tokens[id].totalMinted += amount + supplyRoyaltyAmount; } /// @notice Mint batch function that 1) checks quantity and 2) handles supply royalty 3) keeps track of allowed tokens /// @param to to mint to /// @param ids token ids to mint /// @param amounts of tokens to mint /// @param data as specified by 1155 standard function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual override { super._mintBatch(to, ids, amounts, data); for (uint256 i = 0; i < ids.length; ++i) { (address supplyRoyaltyRecipient, uint256 supplyRoyaltyAmount) = supplyRoyaltyInfo(ids[i], tokens[ids[i]].totalMinted, amounts[i]); _requireCanMintQuantity(ids[i], amounts[i] + supplyRoyaltyAmount); if (supplyRoyaltyAmount > 0) { super._mint(supplyRoyaltyRecipient, ids[i], supplyRoyaltyAmount, data); } tokens[ids[i]].totalMinted += amounts[i] + supplyRoyaltyAmount; } } /// @notice Burns a batch of tokens /// @dev Only the current owner is allowed to burn /// @param from the user to burn from /// @param tokenIds The token ID to burn /// @param amounts The amount of tokens to burn function burnBatch(address from, uint256[] calldata tokenIds, uint256[] calldata amounts) external { if (from != msg.sender && !isApprovedForAll(from, msg.sender)) { revert Burn_NotOwnerOrApproved(msg.sender, from); } _burnBatch(from, tokenIds, amounts); } function setTransferHook(ITransferHookReceiver transferHook) external onlyAdmin(CONTRACT_BASE_ID) { if (address(transferHook) != address(0)) { if (!transferHook.supportsInterface(type(ITransferHookReceiver).interfaceId)) { revert Config_TransferHookNotSupported(address(transferHook)); } } config.transferHook = transferHook; emit ConfigUpdated(msg.sender, ConfigUpdate.TRANSFER_HOOK, config); } /// @notice Hook before token transfer that checks for a transfer hook integration /// @param operator operator moving the tokens /// @param from from address /// @param to to address /// @param ids token ids to move /// @param amounts amounts of tokens /// @param data data of tokens function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal override { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); if (address(config.transferHook) != address(0)) { config.transferHook.onTokenTransferBatch({target: address(this), operator: operator, from: from, to: to, ids: ids, amounts: amounts, data: data}); } } /// @notice Returns the URI for the contract function contractURI() external view returns (string memory) { IRenderer1155 customRenderer = getCustomRenderer(CONTRACT_BASE_ID); if (address(customRenderer) != address(0)) { return customRenderer.contractURI(); } return uri(0); } /// @notice Returns the URI for a token /// @param tokenId The token ID to return the URI for function uri(uint256 tokenId) public view override(ERC1155Upgradeable, IERC1155MetadataURIUpgradeable) returns (string memory) { if (bytes(tokens[tokenId].uri).length > 0) { return tokens[tokenId].uri; } return _render(tokenId); } /// @notice Internal setter for contract admin with no access checks /// @param newOwner new owner address function _setOwner(address newOwner) internal { address lastOwner = config.owner; config.owner = newOwner; emit OwnershipTransferred(lastOwner, newOwner); emit ConfigUpdated(msg.sender, ConfigUpdate.OWNER, config); } /// @notice Internal no-checks set funds recipient address /// @param fundsRecipient new funds recipient address function setFundsRecipient(address payable fundsRecipient) external onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_FUNDS_MANAGER) { config.fundsRecipient = fundsRecipient; emit ConfigUpdated(msg.sender, ConfigUpdate.FUNDS_RECIPIENT, config); } /// @notice Internal no-checks set funds recipient address /// @param fundsRecipient new funds recipient address function _setFundsRecipient(address payable fundsRecipient) internal { config.fundsRecipient = fundsRecipient; emit ConfigUpdated(msg.sender, ConfigUpdate.FUNDS_RECIPIENT, config); } /// @notice Withdraws all ETH from the contract to the message sender function withdraw() public onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_FUNDS_MANAGER) { uint256 contractValue = address(this).balance; if (!TransferHelperUtils.safeSendETH(config.fundsRecipient, contractValue)) { revert ETHWithdrawFailed(config.fundsRecipient, contractValue); } } /// /// /// MANAGER UPGRADE /// /// /// /// @notice Ensures the caller is authorized to upgrade the contract /// @dev This function is called in `upgradeTo` & `upgradeToAndCall` /// @param _newImpl The new implementation address function _authorizeUpgrade(address _newImpl) internal override onlyAdmin(CONTRACT_BASE_ID) {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1155MetadataURI.sol) pragma solidity ^0.8.0; import "../token/ERC1155/extensions/IERC1155MetadataURIUpgradeable.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165Upgradeable.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822ProxiableUpgradeable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeaconUpgradeable.sol"; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; import "../../utils/StorageSlotUpgradeable.sol"; import "../utils/Initializable.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967UpgradeUpgradeable is Initializable { function __ERC1967Upgrade_init() internal onlyInitializing { } function __ERC1967Upgrade_init_unchained() internal onlyInitializing { } // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { _functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS( address newImplementation, bytes memory data, bool forceCall ) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data); } } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) { require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed"); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeaconUpgradeable { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Internal function that returns the initialized version. Returns `_initialized` */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Internal function that returns the initialized version. Returns `_initializing` */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../ERC1967/ERC1967UpgradeUpgradeable.sol"; import "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable { function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeTo(address newImplementation) external virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.0; import "./IERC1155Upgradeable.sol"; import "./IERC1155ReceiverUpgradeable.sol"; import "./extensions/IERC1155MetadataURIUpgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; import "../../utils/ContextUpgradeable.sol"; import "../../utils/introspection/ERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 * * _Available since v3.1._ */ contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155Upgradeable, IERC1155MetadataURIUpgradeable { using AddressUpgradeable for address; // Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) private _balances; // Mapping from account to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ function __ERC1155_init(string memory uri_) internal onlyInitializing { __ERC1155_init_unchained(uri_); } function __ERC1155_init_unchained(string memory uri_) internal onlyInitializing { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) { return interfaceId == type(IERC1155Upgradeable).interfaceId || interfaceId == type(IERC1155MetadataURIUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256) public view virtual override returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: address zero is not a valid owner"); return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual override returns (uint256[] memory) { require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts[i], ids[i]); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not token owner or approved" ); _safeTransferFrom(from, to, id, amount, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not token owner or approved" ); _safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, to, ids, amounts, data); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; emit TransferSingle(operator, from, to, id, amount); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, ids, amounts, data); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; } emit TransferBatch(operator, from, to, ids, amounts); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the amounts in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); _balances[id][to] += amount; emit TransferSingle(operator, address(0), to, id, amount); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { _balances[ids[i]][to] += amounts[i]; } emit TransferBatch(operator, address(0), to, ids, amounts); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); } /** * @dev Destroys `amount` tokens of token type `id` from `from` * * Emits a {TransferSingle} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `amount` tokens of token type `id`. */ function _burn( address from, uint256 id, uint256 amount ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } emit TransferSingle(operator, from, address(0), id, amount); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. */ function _burnBatch( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); for (uint256 i = 0; i < ids.length; i++) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } } emit TransferBatch(operator, from, address(0), ids, amounts); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC1155: setting approval status for self"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `ids` and `amounts` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) private { if (to.isContract()) { try IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155ReceiverUpgradeable.onERC1155Received.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non-ERC1155Receiver implementer"); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.isContract()) { try IERC1155ReceiverUpgradeable(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155ReceiverUpgradeable.onERC1155BatchReceived.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non-ERC1155Receiver implementer"); } } } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[47] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155ReceiverUpgradeable is IERC165Upgradeable { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155Upgradeable is IERC165Upgradeable { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.0; import "../IERC1155Upgradeable.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ interface IERC1155MetadataURIUpgradeable is IERC1155Upgradeable { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol) pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlotUpgradeable { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// 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); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {TransferHelperUtils} from "../utils/TransferHelperUtils.sol"; import {IMintFeeManager} from "../interfaces/IMintFeeManager.sol"; /// @title MintFeeManager /// @notice Manages mint fees for an 1155 contract contract MintFeeManager is IMintFeeManager { uint256 public immutable mintFee; address public immutable mintFeeRecipient; constructor(uint256 _mintFee, address _mintFeeRecipient) { // Set fixed finders fee if (_mintFee >= 0.1 ether) { revert MintFeeCannotBeMoreThanZeroPointOneETH(_mintFee); } if (_mintFeeRecipient == address(0) && _mintFee > 0) { revert CannotSetMintFeeToZeroAddress(); } mintFeeRecipient = _mintFeeRecipient; mintFee = _mintFee; } /// @notice Sends the mint fee to the mint fee recipient and returns the amount of ETH remaining that can be used in this transaction /// @param _quantity The amount of toknens being minted function _handleFeeAndGetValueSent(uint256 _quantity) internal returns (uint256 ethValueSent) { ethValueSent = msg.value; // Handle mint fee if (mintFeeRecipient != address(0)) { uint256 totalFee = mintFee * _quantity; ethValueSent -= totalFee; if (!TransferHelperUtils.safeSendETHLowLimit(mintFeeRecipient, totalFee)) { revert CannotSendMintFee(mintFeeRecipient, totalFee); } } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /// @notice Creator Commands used by minter modules passed back to the main modules interface ICreatorCommands { /// @notice This enum is used to define supported creator action types. /// This can change in the future enum CreatorActions { // No operation - also the default for mintings that may not return a command NO_OP, // Send ether SEND_ETH, // Mint operation MINT } /// @notice This command is for struct Command { // Method for operation CreatorActions method; // Arguments used for this operation bytes args; } /// @notice This command set is returned from the minter back to the user struct CommandSet { Command[] commands; uint256 at; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /// @notice Generic control interface for bit-based permissions-control interface ICreatorPermissionControl { /// @notice Emitted when permissions are updated event UpdatedPermissions(uint256 indexed tokenId, address indexed user, uint256 indexed permissions); /// @notice Public interface to get permissions given a token id and a user address /// @return Returns raw permission bits function getPermissions(uint256 tokenId, address user) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {IRenderer1155} from "./IRenderer1155.sol"; /// @notice Interface for creator renderer controls interface ICreatorRendererControl { /// @notice Get the custom renderer contract (if any) for the given token id /// @dev Reverts if not custom renderer is set for this token function getCustomRenderer(uint256 tokenId) external view returns (IRenderer1155 renderer); error NoRendererForToken(uint256 tokenId); error RendererNotValid(address renderer); event RendererUpdated(uint256 indexed tokenId, address indexed renderer, address indexed user); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol"; interface ICreatorRoyaltiesControl is IERC2981 { /// @notice The RoyaltyConfiguration struct is used to store the royalty configuration for a given token. /// @param royaltyMintSchedule Every nth token will go to the royalty recipient. /// @param royaltyBPS The royalty amount in basis points for secondary sales. /// @param royaltyRecipient The address that will receive the royalty payments. struct RoyaltyConfiguration { uint32 royaltyMintSchedule; uint32 royaltyBPS; address royaltyRecipient; } /// @notice Thrown when a user tries to have 100% supply royalties error InvalidMintSchedule(); /// @notice Event emitted when royalties are updated event UpdatedRoyalties(uint256 indexed tokenId, address indexed user, RoyaltyConfiguration configuration); /// @notice External data getter to get royalties for a token /// @param tokenId tokenId to get royalties configuration for function getRoyalties(uint256 tokenId) external view returns (RoyaltyConfiguration memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; interface ILegacyNaming { function name() external returns (string memory); function symbol() external returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; interface IMintFeeManager { error MintFeeCannotBeMoreThanZeroPointOneETH(uint256 mintFeeBPS); error CannotSendMintFee(address mintFeeRecipient, uint256 mintFee); error CannotSetMintFeeToZeroAddress(); function mintFee() external view returns (uint256); function mintFeeRecipient() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol"; import {ICreatorCommands} from "./ICreatorCommands.sol"; /// @notice Minter standard interface /// @dev Minters need to confirm to the ERC165 selector of type(IMinter1155).interfaceId interface IMinter1155 is IERC165Upgradeable { function requestMint( address sender, uint256 tokenId, uint256 quantity, uint256 ethValueSent, bytes calldata minterArguments ) external returns (ICreatorCommands.CommandSet memory commands); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; interface IOwnable { function owner() external returns (address); event OwnershipTransferred(address lastOwner, address newOwner); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol"; /// @dev IERC165 type required interface IRenderer1155 is IERC165Upgradeable { /// @notice Called for assigned tokenId, or when token id is globally set to a renderer /// @dev contract target is assumed to be msg.sender /// @param tokenId token id to get uri for function uri(uint256 tokenId) external view returns (string memory); /// @notice Only called for tokenId == 0 /// @dev contract target is assumed to be msg.sender function contractURI() external view returns (string memory); /// @notice Sets up renderer from contract /// @param initData data to setup renderer with /// @dev contract target is assumed to be msg.sender function setup(bytes memory initData) external; // IERC165 type required – set in base helper }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol"; interface ITransferHookReceiver is IERC165Upgradeable { /// @notice Token transfer batch callback /// @param target target contract for transfer /// @param operator operator address for transfer /// @param from user address for amount transferred /// @param to user address for amount transferred /// @param ids list of token ids transferred /// @param amounts list of values transferred /// @param data data as perscribed by 1155 standard function onTokenTransferBatch( address target, address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) external; // IERC165 type required }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; interface IVersionedContract { function contractVersion() external returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol"; import {IERC1155MetadataURIUpgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC1155MetadataURIUpgradeable.sol"; import {IZoraCreator1155TypesV1} from "../nft/IZoraCreator1155TypesV1.sol"; import {IRenderer1155} from "../interfaces/IRenderer1155.sol"; import {IMinter1155} from "../interfaces/IMinter1155.sol"; import {IOwnable} from "../interfaces/IOwnable.sol"; import {IVersionedContract} from "./IVersionedContract.sol"; import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol"; /* ░░░░░░░░░░░░░░ ░░▒▒░░░░░░░░░░░░░░░░░░░░ ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░ ░░▒▒▒▒░░░░░░░░░░░░░░ ░░░░░░░░ ░▓▓▒▒▒▒░░░░░░░░░░░░ ░░░░░░░ ░▓▓▓▒▒▒▒░░░░░░░░░░░░ ░░░░░░░░ ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░ ░░░░░░░░░░ ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░ ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░ ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░ ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░ ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░ ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░ OURS TRULY, */ /// @notice Main interface for the ZoraCreator1155 contract /// @author @iainnash / @tbtstl interface IZoraCreator1155 is IZoraCreator1155TypesV1, IVersionedContract, IOwnable, IERC1155MetadataURIUpgradeable { function PERMISSION_BIT_ADMIN() external returns (uint256); function PERMISSION_BIT_MINTER() external returns (uint256); function PERMISSION_BIT_SALES() external returns (uint256); function PERMISSION_BIT_METADATA() external returns (uint256); /// @notice Used to label the configuration update type enum ConfigUpdate { OWNER, FUNDS_RECIPIENT, TRANSFER_HOOK } event ConfigUpdated(address indexed updater, ConfigUpdate indexed updateType, ContractConfig newConfig); event UpdatedToken(address indexed from, uint256 indexed tokenId, TokenData tokenData); event SetupNewToken(uint256 indexed tokenId, address indexed sender, string newURI, uint256 maxSupply); function setOwner(address newOwner) external; event ContractRendererUpdated(IRenderer1155 renderer); event ContractMetadataUpdated(address indexed updater, string uri, string name); event Purchased(address indexed sender, address indexed minter, uint256 indexed tokenId, uint256 quantity, uint256 value); error TokenIdMismatch(uint256 expected, uint256 actual); error NotAllowedContractBaseIDUpdate(); error UserMissingRoleForToken(address user, uint256 tokenId, uint256 role); error Config_TransferHookNotSupported(address proposedAddress); error Mint_InsolventSaleTransfer(); error Mint_ValueTransferFail(); error Mint_TokenIDMintNotAllowed(); error Mint_UnknownCommand(); error Burn_NotOwnerOrApproved(address operator, address user); error NewOwnerNeedsToBeAdmin(); error Sale_CannotCallNonSalesContract(address targetContract); error Sale_CallFailed(); error Renderer_CallFailed(bytes reason); error Renderer_NotValidRendererContract(); error ETHWithdrawFailed(address recipient, uint256 amount); error FundsWithdrawInsolvent(uint256 amount, uint256 contractValue); error CannotMintMoreTokens(uint256 tokenId, uint256 quantity, uint256 totalMinted, uint256 maxSupply); function initialize( string memory newContractURI, ICreatorRoyaltiesControl.RoyaltyConfiguration memory defaultRoyaltyConfiguration, address payable defaultAdmin, bytes[] calldata setupActions ) external; /// @notice Only allow minting one token id at time /// @dev Mint contract function that calls the underlying sales function for commands /// @param minter Address for the minter /// @param tokenId tokenId to mint, set to 0 for new tokenId /// @param quantity to mint /// @param minterArguments calldata for the minter contracts function mint(IMinter1155 minter, uint256 tokenId, uint256 quantity, bytes calldata minterArguments) external payable; function adminMint(address recipient, uint256 tokenId, uint256 quantity, bytes memory data) external; function adminMintBatch(address recipient, uint256[] memory tokenIds, uint256[] memory quantities, bytes memory data) external; function burnBatch(address user, uint256[] calldata tokenIds, uint256[] calldata amounts) external; /// @notice Contract call to setupNewToken /// @param tokenURI URI for the token /// @param maxSupply maxSupply for the token, set to 0 for open edition function setupNewToken(string memory tokenURI, uint256 maxSupply) external returns (uint256 tokenId); function updateTokenURI(uint256 tokenId, string memory _newURI) external; function updateContractMetadata(string memory _newURI, string memory _newName) external; function setTokenMetadataRenderer(uint256 tokenId, IRenderer1155 renderer, bytes calldata setupData) external; function contractURI() external view returns (string memory); function assumeLastTokenIdMatches(uint256 tokenId) external; function updateRoyaltiesForToken(uint256 tokenId, ICreatorRoyaltiesControl.RoyaltyConfiguration memory royaltyConfiguration) external; function addPermission(uint256 tokenId, address user, uint256 permissionBits) external; function removePermission(uint256 tokenId, address user, uint256 permissionBits) external; function isAdminOrRole(address user, uint256 tokenId, uint256 role) external view returns (bool); function getTokenInfo(uint256 tokenId) external view returns (TokenData memory); function callRenderer(uint256 tokenId, bytes memory data) external; function callSale(uint256 tokenId, IMinter1155 salesConfig, bytes memory data) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {ILegacyNaming} from "../interfaces/ILegacyNaming.sol"; import {LegacyNamingStorageV1} from "./LegacyNamingStorageV1.sol"; /// @title LegacyNamingControl /// @notice Contract for managing the name and symbol of an 1155 contract in the legacy naming scheme contract LegacyNamingControl is LegacyNamingStorageV1, ILegacyNaming { /// @notice The name of the contract function name() external view returns (string memory) { return _name; } /// @notice The token symbol of the contract function symbol() external pure returns (string memory) {} function _setName(string memory _newName) internal { _name = _newName; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; contract LegacyNamingStorageV1 { string internal _name; uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {ITransferHookReceiver} from "../interfaces/ITransferHookReceiver.sol"; /* ░░░░░░░░░░░░░░ ░░▒▒░░░░░░░░░░░░░░░░░░░░ ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░ ░░▒▒▒▒░░░░░░░░░░░░░░ ░░░░░░░░ ░▓▓▒▒▒▒░░░░░░░░░░░░ ░░░░░░░ ░▓▓▓▒▒▒▒░░░░░░░░░░░░ ░░░░░░░░ ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░ ░░░░░░░░░░ ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░ ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░ ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░ ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░ ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░ ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░ OURS TRULY, */ /// Imagine. Mint. Enjoy. /// @notice Interface for types used across the ZoraCreator1155 contract /// @author @iainnash / @tbtstl interface IZoraCreator1155TypesV1 { /// @notice Used to store individual token data struct TokenData { string uri; uint256 maxSupply; uint256 totalMinted; } /// @notice Used to store contract-level configuration struct ContractConfig { address owner; uint96 __gap1; address payable fundsRecipient; uint96 __gap2; ITransferHookReceiver transferHook; uint96 __gap3; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {IZoraCreator1155TypesV1} from "./IZoraCreator1155TypesV1.sol"; /* ░░░░░░░░░░░░░░ ░░▒▒░░░░░░░░░░░░░░░░░░░░ ░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░ ░░▒▒▒▒░░░░░░░░░░░░░░ ░░░░░░░░ ░▓▓▒▒▒▒░░░░░░░░░░░░ ░░░░░░░ ░▓▓▓▒▒▒▒░░░░░░░░░░░░ ░░░░░░░░ ░▓▓▓▒▒▒▒░░░░░░░░░░░░░░ ░░░░░░░░░░ ░▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░▓▓▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░ ░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░ ░░▓▓▓▓▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░ ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒░░░░░░░░░▒▒▒▒▒░░ ░░▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░ ░░▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░ OURS TRULY, github.com/ourzora/zora-1155-contracts */ /// Imagine. Mint. Enjoy. /// @notice Storage for 1155 contract /// @author @iainnash / @tbtstl contract ZoraCreator1155StorageV1 is IZoraCreator1155TypesV1 { /// @notice token data stored for each token mapping(uint256 => TokenData) internal tokens; /// @notice metadata renderer contract for each token mapping(uint256 => address) public metadataRendererContract; /// @notice next token id available when using a linear mint style (default for launch) uint256 public nextTokenId; /// @notice Global contract configuration ContractConfig config; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {CreatorPermissionStorageV1} from "./CreatorPermissionStorageV1.sol"; import {ICreatorPermissionControl} from "../interfaces/ICreatorPermissionControl.sol"; /// Imagine. Mint. Enjoy. /// @author @iainnash / @tbtstl contract CreatorPermissionControl is CreatorPermissionStorageV1, ICreatorPermissionControl { /// @notice Check if the user has the given permissions /// @dev if multiple permissions are passed in this checks for all the permissions requested /// @return true or false if all of the passed in permissions apply function _hasPermissions(uint256 tokenId, address user, uint256 permissionBits) internal view returns (bool) { // Does a bitwise and and checks if any of those permissions match return permissions[tokenId][user] & permissionBits == permissionBits; } /// @notice Check if the user has any of the given permissions /// @dev if multiple permissions are passed in this checks for any one of those permissions /// @return true or false if any of the passed in permissions apply function _hasAnyPermission(uint256 tokenId, address user, uint256 permissionBits) internal view returns (bool) { // Does a bitwise and and checks if any of those permissions match return permissions[tokenId][user] & permissionBits > 0; } /// @return raw permission bits for the given user function getPermissions(uint256 tokenId, address user) external view returns (uint256) { return permissions[tokenId][user]; } /// @notice addPermission – internal function to add a set of permission bits to a user /// @param tokenId token id to add the permission to (0 indicates contract-wide add) /// @param user user to update permissions for /// @param permissionBits bits to add permissions to function _addPermission(uint256 tokenId, address user, uint256 permissionBits) internal { uint256 tokenPermissions = permissions[tokenId][user]; tokenPermissions |= permissionBits; permissions[tokenId][user] = tokenPermissions; emit UpdatedPermissions(tokenId, user, tokenPermissions); } /// @notice _clearPermission clear permissions for user /// @param tokenId token id to clear permission from (0 indicates contract-wide action) function _clearPermissions(uint256 tokenId, address user) internal { permissions[tokenId][user] = 0; emit UpdatedPermissions(tokenId, user, 0); } /// @notice _removePermission removes permissions for user /// @param tokenId token id to clear permission from (0 indicates contract-wide action) /// @param user user to manage permissions for /// @param permissionBits set of permission bits to remove function _removePermission(uint256 tokenId, address user, uint256 permissionBits) internal { uint256 tokenPermissions = permissions[tokenId][user]; tokenPermissions &= ~permissionBits; permissions[tokenId][user] = tokenPermissions; emit UpdatedPermissions(tokenId, user, tokenPermissions); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /// Imagine. Mint. Enjoy. /// @author @iainnash / @tbtstl contract CreatorPermissionStorageV1 { mapping(uint256 => mapping(address => uint256)) public permissions; uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {CreatorRendererStorageV1} from "./CreatorRendererStorageV1.sol"; import {IRenderer1155} from "../interfaces/IRenderer1155.sol"; import {ITransferHookReceiver} from "../interfaces/ITransferHookReceiver.sol"; import {SharedBaseConstants} from "../shared/SharedBaseConstants.sol"; /// @title CreatorRendererControl /// @notice Contract for managing the renderer of an 1155 contract abstract contract CreatorRendererControl is CreatorRendererStorageV1, SharedBaseConstants { function _setRenderer(uint256 tokenId, IRenderer1155 renderer, bytes calldata setupData) internal { if (address(renderer) == address(0)) { delete customRenderers[tokenId]; } else { customRenderers[tokenId] = renderer; if (!renderer.supportsInterface(type(IRenderer1155).interfaceId)) { revert RendererNotValid(address(renderer)); } renderer.setup(setupData); } emit RendererUpdated({tokenId: tokenId, renderer: address(renderer), user: msg.sender}); } /// @notice Return the renderer for a given token /// @dev Returns address 0 for no results /// @param tokenId The token to get the renderer for function getCustomRenderer(uint256 tokenId) public view returns (IRenderer1155 customRenderer) { customRenderer = customRenderers[tokenId]; if (address(customRenderer) == address(0)) { customRenderer = customRenderers[CONTRACT_BASE_ID]; } } /// @notice Function called to render when an empty tokenURI exists on the contract function _render(uint256 tokenId) internal view returns (string memory) { return getCustomRenderer(tokenId).uri(tokenId); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {ICreatorRendererControl} from "../interfaces/ICreatorRendererControl.sol"; import {IRenderer1155} from "../interfaces/IRenderer1155.sol"; /// @notice Creator Renderer Storage Configuration Contract V1 abstract contract CreatorRendererStorageV1 is ICreatorRendererControl { /// @notice Mapping for custom renderers mapping(uint256 => IRenderer1155) public customRenderers; uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {CreatorRoyaltiesStorageV1} from "./CreatorRoyaltiesStorageV1.sol"; import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol"; import {SharedBaseConstants} from "../shared/SharedBaseConstants.sol"; import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol"; /// Imagine. Mint. Enjoy. /// @title CreatorRoyaltiesControl /// @author ZORA @iainnash / @tbtstl /// @notice Contract for managing the royalties of an 1155 contract abstract contract CreatorRoyaltiesControl is CreatorRoyaltiesStorageV1, SharedBaseConstants { uint256 immutable ROYALTY_BPS_TO_PERCENT = 10_000; /// @notice The royalty information for a given token. /// @param tokenId The token ID to get the royalty information for. function getRoyalties(uint256 tokenId) public view returns (RoyaltyConfiguration memory) { RoyaltyConfiguration memory config = royalties[tokenId]; if (config.royaltyRecipient != address(0)) { return config; } // Otherwise, return default. return royalties[CONTRACT_BASE_ID]; } /// @notice Returns the royalty information for a given token. /// @param tokenId The token ID to get the royalty information for. /// @param salePrice The sale price of the NFT asset specified by tokenId function royaltyInfo(uint256 tokenId, uint256 salePrice) public view returns (address receiver, uint256 royaltyAmount) { RoyaltyConfiguration memory config = getRoyalties(tokenId); royaltyAmount = (config.royaltyBPS * salePrice) / ROYALTY_BPS_TO_PERCENT; receiver = config.royaltyRecipient; } /// @notice Returns the supply royalty information for a given token. /// @param tokenId The token ID to get the royalty information for. /// @param mintAmount The amount of tokens being minted. /// @param totalSupply The total supply of the token, function supplyRoyaltyInfo(uint256 tokenId, uint256 totalSupply, uint256 mintAmount) public view returns (address receiver, uint256 royaltyAmount) { RoyaltyConfiguration memory config = getRoyalties(tokenId); if (config.royaltyMintSchedule == 0) { return (config.royaltyRecipient, 0); } uint256 totalRoyaltyMints = (mintAmount + (totalSupply % config.royaltyMintSchedule)) / (config.royaltyMintSchedule - 1); return (config.royaltyRecipient, totalRoyaltyMints); } function _updateRoyalties(uint256 tokenId, RoyaltyConfiguration memory configuration) internal { // Don't allow 100% supply royalties if (configuration.royaltyMintSchedule == 1) { revert InvalidMintSchedule(); } royalties[tokenId] = configuration; emit UpdatedRoyalties(tokenId, msg.sender, configuration); } function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC2981).interfaceId; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol"; /// Imagine. Mint. Enjoy. /// @title CreatorRoyaltiesControl /// @author ZORA @iainnash / @tbtstl /// @notice Royalty storage contract pattern abstract contract CreatorRoyaltiesStorageV1 is ICreatorRoyaltiesControl { mapping(uint256 => RoyaltyConfiguration) public royalties; uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; contract SharedBaseConstants { uint256 public immutable CONTRACT_BASE_ID = 0; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import "@openzeppelin/contracts/utils/Address.sol"; /// @title PublicMulticall /// @notice Contract for executing a batch of function calls on this contract abstract contract PublicMulticall { /** * @notice Receives and executes a batch of function calls on this contract. */ function multicall(bytes[] calldata data) public virtual returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { results[i] = Address.functionDelegateCall(address(this), data[i]); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /// @title TransferHelperUtils /// @notice Helper functions for sending ETH library TransferHelperUtils { /// @dev Gas limit to send funds uint256 internal constant FUNDS_SEND_LOW_GAS_LIMIT = 110_000; // @dev Gas limit to send funds – usable for splits, can use with withdraws uint256 internal constant FUNDS_SEND_GAS_LIMIT = 310_000; /// @notice Sends ETH to a recipient, making conservative estimates to not run out of gas /// @param recipient The address to send ETH to /// @param value The amount of ETH to send function safeSendETHLowLimit(address recipient, uint256 value) internal returns (bool success) { (success, ) = recipient.call{value: value, gas: FUNDS_SEND_LOW_GAS_LIMIT}(""); } /// @notice Sends ETH to a recipient, making an attempt to not run out of gas /// @param recipient The address to send ETH to /// @param value The amount of ETH to send function safeSendETH(address recipient, uint256 value) internal returns (bool success) { (success, ) = recipient.call{value: value, gas: FUNDS_SEND_GAS_LIMIT}(""); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {IVersionedContract} from "../interfaces/IVersionedContract.sol"; /// @title ContractVersionBase /// @notice Base contract for versioning contracts contract ContractVersionBase is IVersionedContract { /// @notice The version of the contract function contractVersion() external pure override returns (string memory) { return "1.0.0"; } }
{ "remappings": [ "@openzeppelin/=node_modules/@openzeppelin/", "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", "_imagine/=_imagine/", "ds-test/=node_modules/ds-test/src/", "forge-std/=node_modules/forge-std/src/", "mint/=_imagine/mint/" ], "optimizer": { "enabled": true, "runs": 5000 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"_mintFeeAmount","type":"uint256"},{"internalType":"address","name":"_mintFeeRecipient","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"user","type":"address"}],"name":"Burn_NotOwnerOrApproved","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"totalMinted","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"}],"name":"CannotMintMoreTokens","type":"error"},{"inputs":[{"internalType":"address","name":"mintFeeRecipient","type":"address"},{"internalType":"uint256","name":"mintFee","type":"uint256"}],"name":"CannotSendMintFee","type":"error"},{"inputs":[],"name":"CannotSetMintFeeToZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"proposedAddress","type":"address"}],"name":"Config_TransferHookNotSupported","type":"error"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ETHWithdrawFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"contractValue","type":"uint256"}],"name":"FundsWithdrawInsolvent","type":"error"},{"inputs":[],"name":"InvalidMintSchedule","type":"error"},{"inputs":[{"internalType":"uint256","name":"mintFeeBPS","type":"uint256"}],"name":"MintFeeCannotBeMoreThanZeroPointOneETH","type":"error"},{"inputs":[],"name":"Mint_InsolventSaleTransfer","type":"error"},{"inputs":[],"name":"Mint_TokenIDMintNotAllowed","type":"error"},{"inputs":[],"name":"Mint_UnknownCommand","type":"error"},{"inputs":[],"name":"Mint_ValueTransferFail","type":"error"},{"inputs":[],"name":"NewOwnerNeedsToBeAdmin","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NoRendererForToken","type":"error"},{"inputs":[],"name":"NotAllowedContractBaseIDUpdate","type":"error"},{"inputs":[{"internalType":"address","name":"renderer","type":"address"}],"name":"RendererNotValid","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"Renderer_CallFailed","type":"error"},{"inputs":[],"name":"Renderer_NotValidRendererContract","type":"error"},{"inputs":[],"name":"Sale_CallFailed","type":"error"},{"inputs":[{"internalType":"address","name":"targetContract","type":"address"}],"name":"Sale_CannotCallNonSalesContract","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"TokenIdMismatch","type":"error"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"role","type":"uint256"}],"name":"UserMissingRoleForToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"updater","type":"address"},{"indexed":true,"internalType":"enum IZoraCreator1155.ConfigUpdate","name":"updateType","type":"uint8"},{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint96","name":"__gap1","type":"uint96"},{"internalType":"address payable","name":"fundsRecipient","type":"address"},{"internalType":"uint96","name":"__gap2","type":"uint96"},{"internalType":"contract ITransferHookReceiver","name":"transferHook","type":"address"},{"internalType":"uint96","name":"__gap3","type":"uint96"}],"indexed":false,"internalType":"struct IZoraCreator1155TypesV1.ContractConfig","name":"newConfig","type":"tuple"}],"name":"ConfigUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"updater","type":"address"},{"indexed":false,"internalType":"string","name":"uri","type":"string"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"ContractMetadataUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IRenderer1155","name":"renderer","type":"address"}],"name":"ContractRendererUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"lastOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Purchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"renderer","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"RendererUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"string","name":"newURI","type":"string"},{"indexed":false,"internalType":"uint256","name":"maxSupply","type":"uint256"}],"name":"SetupNewToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"permissions","type":"uint256"}],"name":"UpdatedPermissions","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"components":[{"internalType":"uint32","name":"royaltyMintSchedule","type":"uint32"},{"internalType":"uint32","name":"royaltyBPS","type":"uint32"},{"internalType":"address","name":"royaltyRecipient","type":"address"}],"indexed":false,"internalType":"struct ICreatorRoyaltiesControl.RoyaltyConfiguration","name":"configuration","type":"tuple"}],"name":"UpdatedRoyalties","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"string","name":"uri","type":"string"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"totalMinted","type":"uint256"}],"indexed":false,"internalType":"struct IZoraCreator1155TypesV1.TokenData","name":"tokenData","type":"tuple"}],"name":"UpdatedToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"CONTRACT_BASE_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMISSION_BIT_ADMIN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMISSION_BIT_FUNDS_MANAGER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMISSION_BIT_METADATA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMISSION_BIT_MINTER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMISSION_BIT_SALES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"permissionBits","type":"uint256"}],"name":"addPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"adminMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"quantities","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"adminMintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lastTokenId","type":"uint256"}],"name":"assumeLastTokenIdMatches","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"burnBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"callRenderer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"contract IMinter1155","name":"salesConfig","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"callSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"customRenderers","outputs":[{"internalType":"contract IRenderer1155","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getCustomRenderer","outputs":[{"internalType":"contract IRenderer1155","name":"customRenderer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"getPermissions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getRoyalties","outputs":[{"components":[{"internalType":"uint32","name":"royaltyMintSchedule","type":"uint32"},{"internalType":"uint32","name":"royaltyBPS","type":"uint32"},{"internalType":"address","name":"royaltyRecipient","type":"address"}],"internalType":"struct ICreatorRoyaltiesControl.RoyaltyConfiguration","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getTokenInfo","outputs":[{"components":[{"internalType":"string","name":"uri","type":"string"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"totalMinted","type":"uint256"}],"internalType":"struct IZoraCreator1155TypesV1.TokenData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"newContractURI","type":"string"},{"components":[{"internalType":"uint32","name":"royaltyMintSchedule","type":"uint32"},{"internalType":"uint32","name":"royaltyBPS","type":"uint32"},{"internalType":"address","name":"royaltyRecipient","type":"address"}],"internalType":"struct ICreatorRoyaltiesControl.RoyaltyConfiguration","name":"defaultRoyaltyConfiguration","type":"tuple"},{"internalType":"address payable","name":"defaultAdmin","type":"address"},{"internalType":"bytes[]","name":"setupActions","type":"bytes[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"role","type":"uint256"}],"name":"isAdminOrRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"metadataRendererContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IMinter1155","name":"minter","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes","name":"minterArguments","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintFeeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"permissions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"permissionBits","type":"uint256"}],"name":"removePermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"royalties","outputs":[{"internalType":"uint32","name":"royaltyMintSchedule","type":"uint32"},{"internalType":"uint32","name":"royaltyBPS","type":"uint32"},{"internalType":"address","name":"royaltyRecipient","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"fundsRecipient","type":"address"}],"name":"setFundsRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"contract IRenderer1155","name":"renderer","type":"address"},{"internalType":"bytes","name":"setupData","type":"bytes"}],"name":"setTokenMetadataRenderer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ITransferHookReceiver","name":"transferHook","type":"address"}],"name":"setTransferHook","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newURI","type":"string"},{"internalType":"uint256","name":"maxSupply","type":"uint256"}],"name":"setupNewToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"supplyRoyaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"string","name":"_newURI","type":"string"},{"internalType":"string","name":"_newName","type":"string"}],"name":"updateContractMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"uint32","name":"royaltyMintSchedule","type":"uint32"},{"internalType":"uint32","name":"royaltyBPS","type":"uint32"},{"internalType":"address","name":"royaltyRecipient","type":"address"}],"internalType":"struct ICreatorRoyaltiesControl.RoyaltyConfiguration","name":"newConfiguration","type":"tuple"}],"name":"updateRoyaltiesForToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"_newURI","type":"string"}],"name":"updateTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101c034620003b5576200637590601f38839003908101601f19168201906001600160401b03821183831017620003ba5780839160409586948552833981010312620003b55780516020909101516001600160a01b038116808203620003b55767016345785d8a00008310156200039d57158062000393575b620003825760a0526080523060c0526000908160e052610100916127108352610120916002835261014060048152610160906008825261018092601084526101a09460208652805460ff8160081c16159081809262000374575b80156200035b575b15620003005760ff198116600117835581620002ee575b50620002b4575b505194615fa49687620003d18839608051878181612376015261411e015260a051878181611db30152611e76015260c051878181612e4a01528181612f440152613520015260e0518781816106ff01528181610a3701528181610def0152818161118a01528181611c0e015281816127ef01528181612a6201528181612b5d01528181612c3601528181612c8701528181612fa5015281816134710152818161358001528181613b8d01528181614059015281816141840152818161435d01528181614fd30152818161508c015281816156f60152818161583101528181615b700152615c0401525186613a5f0152518581816106ab01528181610f1f015281816111670152818161161d015281816128fb01528181612a3501528181612c1401528181612c6501528181613ad10152818161408501528181614f17015261502401525184818161061601528181610c4e01528181610dce015281816111410152818161155e0152611e40015251838181610c240152613d4a015251828181610689015281816117ba0152818161197901528181613b650152613dc60152518181816116be01528181611a740152818161345001526141630152f35b61ff001981541690557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024986020825160018152a138620000f8565b61ffff191661010117825538620000f1565b835162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b50303b158015620000da5750600160ff821614620000da565b50600160ff821610620000d2565b825163c64a448960e01b8152600490fd5b5081151562000078565b8351637f19df9f60e11b815260048101849052602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608060405260048036101561001357600080fd5b600090813560e01c8062fdd58e14614380578063011442011461434557806301ffc9a7146142a557806306fdde03146141ce5780630e89341c146141ae57806310a7eb5d1461414157806313966db51461410657806313af40351461403957806316680fad14613d6d57806318711c7d14613d3257806318e97fd114613b2957806323bd038614613aad5780632a55205a14613a1e5780632eb2c2d614613721578063300ecdb9146133f15780633659cfe6146134f95780633ccfd60b1461343a5780634913162d146133f15780634e1273f4146132425780634f1ef28614612f0457806352d1902d14612e2d5780635b2f6347146129665780635d0f6cba146127c757806369a5b302146127945780636b20c45414612423578063731133e914611df657806375794a3c14611dd7578063765b0c3614611d935780637f2dc61c14611be35780637f77f57414611b955780638621ea4b14611b545780638c7a63ae14611ae15780638da5cb5b14611ab95780638ec998a014611a97578063929a712814611a5c57806395d89b41146119fe5780639c5c63c914611933578063a0a8e460146118d5578063a22cb465146117dd578063a453eaf0146117a2578063ac9650d8146116ec578063afed7e9e14611698578063bb3bafd614611640578063c046435614611605578063c238d1ee1461150b578063d1ad846b146110c6578063d258609a14610d92578063d904b94a14610bd7578063dd15e05f14610ba4578063e72878b414610b47578063e74d86c214610b17578063e8a3d48514610ae3578063e985e9c514610a8e578063ef71c82e1461063c578063f1b0d6bb146105fe5763f242432a1461028657600080fd5b346105fa5760a06003193601126105fa5761029f6143b0565b6102a76143c6565b90604435906064359060843567ffffffffffffffff81116105f6576102cf9036908701614546565b916001600160a01b039161031c848483169433861480156105cf575b6102f490614a3b565b881692610302841515614aac565b61030b88614cf6565b8961031587614cf6565b92336155f5565b84885260209560978752604089208460005287528260406000205461034382821015614b1d565b878b526097895260408b20866000528952036040600020558589526097875260408920826000528752604060002061037c848254614b8e565b90558184604051888152858a8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6260403392a43b6103ba578780f35b869460008794610417604051978896879586947ff23a6e61000000000000000000000000000000000000000000000000000000009c8d8752339087015260248601526044850152606484015260a0608484015260a48301906143ff565b03925af1600091816105a0575b506104fe575050600190610436614c69565b6308c379a0146104ca575b5061045357505b388080808080808780f35b6104c69060405191829162461bcd60e51b8352820160809060208152603460208201527f455243313135353a207472616e7366657220746f206e6f6e2d4552433131353560408201527f526563656976657220696d706c656d656e74657200000000000000000000000060608201520190565b0390fd5b6104d2614c87565b806104dd5750610441565b6104c6849160405193849362461bcd60e51b855284015260248301906143ff565b7fffffffff000000000000000000000000000000000000000000000000000000001603905061052d5750610448565b6104c69060405191829162461bcd60e51b8352820160809060208152602860208201527f455243313135353a204552433131353552656365697665722072656a6563746560408201527f6420746f6b656e7300000000000000000000000000000000000000000000000060608201520190565b6105c1919250843d86116105c8575b6105b981836144d0565b810190614c31565b9038610424565b503d6105af565b50858b52609860205260408b20336000526020526102f460ff6040600020541690506102eb565b8680fd5b5080fd5b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b80fd5b5090346106395760406003193601126106395767ffffffffffffffff918035838111610a8a5761066f9036908301614546565b602435848111610a86576106869036908401614546565b917f0000000000000000000000000000000000000000000000000000000000000000947f000000000000000000000000000000000000000000000000000000000000000095600080526020966101fe88526040600020336000528852818117604060002054161590811591610a2f575b50156109f157507f000000000000000000000000000000000000000000000000000000000000000085526101c6865260408520918351928284116109de5761073e8154614d6e565b93601f9485811161099e575b50808986821160011461093f578991610934575b506000198260011b9260031b1c19161790555b84519182116109215750610193916107898354614d6e565b8181116108c3575b508690821160011461081a57956107fa9392826108099388997f74b7c2afa3f89c562b59674a101e2c48bceeb27cdb620afefa14446f1ffa487b98999161080f575b506000198260011b9260031b1c19161790555b6040519384936040855260408501906143ff565b908382039084015233956143ff565b0390a280f35b9050880151386107d3565b8286527ffc8af01f449989052b52093a58fc9f42d0b11f0c6dd5dca0463dab62346ccc6890601f198316875b8181106108ac5750837f74b7c2afa3f89c562b59674a101e2c48bceeb27cdb620afefa14446f1ffa487b979899936107fa9796936108099660019410610893575b5050811b0190556107e6565b8a015160001960f88460031b161c191690553880610887565b91928960018192868b015181550194019201610846565b8387527ffc8af01f449989052b52093a58fc9f42d0b11f0c6dd5dca0463dab62346ccc688280850160051c8201928a8610610918575b0160051c01905b81811061090d5750610791565b878155600101610900565b925081926108f9565b856041602492634e487b7160e01b835252fd5b90508601513861075e565b838a528a8a2091601f19168a5b8c828210610988575050908360019493921061096f575b5050811b019055610771565b88015160001960f88460031b161c191690553880610963565b600184958293958d01518155019401920161094c565b8289528989208680840160051c8201928c85106109d5575b0160051c01905b8181106109ca575061074a565b8981556001016109bd565b925081926109b6565b602487604184634e487b7160e01b835252fd5b82606491604051917f4baa2a4d0000000000000000000000000000000000000000000000000000000083523390830152600060248301526044820152fd5b610a809150337f00000000000000000000000000000000000000000000000000000000000000006000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b386106f6565b8380fd5b8280fd5b823461063957604060031936011261063957610aa86143b0565b6040610ab26143c6565b926001600160a01b0380931681526098602052209116600052602052602060ff604060002054166040519015158152f35b8234610639578060031936011261063957610b13610aff6156e9565b6040519182916020835260208301906143ff565b0390f35b509034610639576020600319360112610639576020610b368335615b47565b6001600160a01b0360405191168152f35b50346105fa5760206003193601126105fa5780356000196101c8540190808203610b6f578380f35b60449350604051927f4fa09b3f0000000000000000000000000000000000000000000000000000000084528301526024820152fd5b50346105fa5760206003193601126105fa5760406020926001600160a01b039235815261012d8452205416604051908152f35b50346105fa5760606003193601126105fa578035610bf36143c6565b9060443567ffffffffffffffff8111610d8e576001600160a01b03610c1e610c749236908701614546565b93610c4a7f00000000000000000000000000000000000000000000000000000000000000008533614f13565b16917f00000000000000000000000000000000000000000000000000000000000000009083614f13565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f6890e5b30000000000000000000000000000000000000000000000000000000084820152602081602481855afa908115610d83578591610d55575b5015610d2557818492918360208194519301915af1610cf36148c6565b5015610cfd575080f35b6040517fd663a084000000000000000000000000000000000000000000000000000000008152fd5b82602491604051917fe15b8e06000000000000000000000000000000000000000000000000000000008352820152fd5b610d76915060203d8111610d7c575b610d6e81836144d0565b810190615177565b38610cd6565b503d610d64565b6040513d87823e3d90fd5b8480fd5b50903461063957604060031936011261063957813567ffffffffffffffff918282116106395750610dc69036908401614546565b602435610e147f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000033614f13565b610e1c614ebe565b6101c8908154926001928385019055604051610e3781614484565b818152602095868201848152604083019060008252876000526101c6895260406000209284519a8b519182116110b15750610e728454614d6e565b601f811161106c575b5087899a9b60009a98999a508c90601f8411600114610fc157927f1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc0689897959281808c999794600297600093610fb4575b505060001991921b9260031b1c19161784555b518a840155519101557f5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe60405180610f173394826146fb565b0390a3610f457f00000000000000000000000000000000000000000000000000000000000000003385615a7d565b8051610f77575b610f61604051916040835260408301906143ff565b93878201528033940390a3606555604051908152f35b827f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b60405189815280610fac8b8201866143ff565b0390a2610f4c565b0151915060001938610ecb565b908d91601f19859495168860005283600020936000905b82821061103d575050926002959285927f1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc0689c9b99968e9b999610611024575b505050811b018455610ede565b015160001960f88460031b161c19169055388080611017565b92948392949790839297999a9b9c9d9e508887015181550196019401918e9b9a9998979694928e969492610fd8565b846000528a600020601f830160051c8101918c84106110a7575b601f0160051c01905b81811061109c5750610e7b565b60008155890161108f565b9091508190611086565b604190634e487b7160e01b6000525260246000fd5b50346105fa5760031990608082360112610a8a576110e26143b0565b9067ffffffffffffffff6024358181116115075761110390369084016145ca565b926044358281116105f65761111b90369085016145ca565b916064359081116105f6576111369095939536908701614546565b9261113f614ebe565b7f0000000000000000000000000000000000000000000000000000000000000000966111d3887f000000000000000000000000000000000000000000000000000000000000000017337f00000000000000000000000000000000000000000000000000000000000000006000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b1594815b875181101561120d576111ee90876111f3576149ec565b6111d7565b6112088b611201838c614a11565b5133614f13565b6149ec565b5090869291886001600160a01b0386169361122985151561518f565b6112368651895114614b9b565b6112438389888a3361552a565b835b888751821015611297579061125d8161129293614a11565b51611268828a614a11565b5187526020609781526040882090896000525261128b6040600020918254614b8e565b90556149ec565b611245565b905086929495939784876040517f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb3391806112d3888b83614c0c565b0390a43b6113cf575b5050505050805b82518110156113c6576112f68184614a11565b51906113028185614a11565b5183526101c660209080825260029384604087200154611322858b614a11565b519061132d92615c7a565b94909161133a8589614a11565b5186611346878d614a11565b519061135191614b8e565b61135a9161548e565b8786868b8215159961128b97611387956113a39c6113a8575b50505050611381908d614a11565b51614b8e565b93611392868a614a11565b518852526040862001918254614b8e565b6112e3565b6113bc946113b591614a11565b5190615200565b868b828f8d611373565b50600160655580f35b849361142b600061143b9561144b602096604051988997889687957fbc197c81000000000000000000000000000000000000000000000000000000009d8e8852339088015287602488015260a0604488015260a48701906145e5565b90838683030160648701526145e5565b908382030160848401528d6143ff565b03925af1600091816114e7575b506114ba5750506001611469614c69565b6308c379a014611484575b61045357505b84808381876112dc565b61148c614c87565b806114975750611474565b826104c660209260405193849362461bcd60e51b855284015260248301906143ff565b7fffffffff00000000000000000000000000000000000000000000000000000000160361052d575061147a565b61150091925060203d81116105c8576105b981836144d0565b9088611458565b8580fd5b50346105fa5760806003193601126105fa57816115266143b0565b602435926044356064359267ffffffffffffffff8411610d8e5761155186936115d195369101614546565b611559614ebe565b6115847f00000000000000000000000000000000000000000000000000000000000000008533614f13565b8386526115c081846115a581600260406101c69c8d60205220015489615c7a565b9790956115bb6115b58a85614b8e565b8361548e565b615200565b8387816115f3575b50505050614b8e565b9183526020526115e960026040842001918254614b8e565b9055600160655580f35b6115fc93615200565b388083876115c8565b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50903461063957602060031936011261063957610b136116608335615b9c565b6040519182918291909160406001600160a01b0381606084019563ffffffff8082511686526020820151166020860152015116910152565b50346105fa5760806003193601126105fa576116e990356116b836614619565b906116e47f00000000000000000000000000000000000000000000000000000000000000008233614f13565b615ced565b80f35b50346105fa5760209081600319360112610a8a57803567ffffffffffffffff8111610a86576117228492611728923691016146a0565b90615dfa565b60405191838301848452825180915260408401948060408360051b870101940192955b8287106117585785850386f35b909192938280611792837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08a6001960301865288516143ff565b960192019601959291909261174b565b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346105fa5760406003193601126105fa576117f76143b0565b60243590811515809203610a86576001600160a01b03169182331461186b575033835260986020526040832082600052602052604060002060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a380f35b60849060206040519162461bcd60e51b8352820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c6600000000000000000000000000000000000000000000006064820152fd5b8234610639578060031936011261063957610b136040516118f581614452565b600581527f312e302e3000000000000000000000000000000000000000000000000000000060208201526040519182916020835260208301906143ff565b50346105fa5760406003193601126105fa5781602435823567ffffffffffffffff8211610a8a576001600160a01b036119a4611973859436908801614546565b9261199f7f00000000000000000000000000000000000000000000000000000000000000008233614f13565b615b47565b1682602083519301915af16119b76148c6565b90156119c1578280f35b906104c66020926040519384937f4f424e0800000000000000000000000000000000000000000000000000000000855284015260248301906143ff565b823461063957806003193601126106395760405160208082528160605191828183015260005b838110611a46575050601f19601f836000604080968601015201168101030190f35b6080810151858201604001528492508101611a24565b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b8234610639576116e9611aa9366146d1565b91611ab48133615022565b615a7d565b823461063957806003193601126106395760206001600160a01b036101c95416604051908152f35b50346105fa5760206003193601126105fa5781604091610b1393838051611b0781614484565b6060815282602082015201523581526101c660205220600260405191611b2c83614484565b611b3581614da8565b83526001810154602084015201546040820152604051918291826146fb565b50346105fa5760606003193601126105fa57611b7890604435906024359035615c7a565b604080516001600160a01b03939093168352602083019190915290f35b50346105fa5760206003193601126105fa5760609160409135815261016060205220546001600160a01b036040519163ffffffff80821684528160201c16602084015260401c166040820152f35b50346105fa5760206003193601126105fa578035906001600160a01b038216809203610a8a57611c337f000000000000000000000000000000000000000000000000000000000000000033615022565b81611cd4575b506101cb9073ffffffffffffffffffffffffffffffffffffffff1982541617905560026040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f339180611cce819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b0390a380f35b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f80b10ace0000000000000000000000000000000000000000000000000000000082820152602081602481865afa908115611d88578491611d6a575b50611c3957602491604051917f17ce9560000000000000000000000000000000000000000000000000000000008352820152fd5b611d82915060203d8111610d7c57610d6e81836144d0565b38611d36565b6040513d86823e3d90fd5b823461063957806003193601126106395760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461063957806003193601126106395760206101c854604051908152f35b5090608060031936011261063957611e0c6143b0565b906044359160643567ffffffffffffffff8111610a8a57611e309036908601614424565b611e3b929192614ebe565b611e717f00000000000000000000000000000000000000000000000000000000000000006024356001600160a01b038516614f13565b8334937f0000000000000000000000000000000000000000000000000000000000000000926001600160a01b03841661236d575b611eff935060405193849283927f6890e5b3000000000000000000000000000000000000000000000000000000008452308c85015260243560248501528a604485015288606485015260a0608485015260a484019161510f565b0381836001600160a01b0387165af1908115611d885784916121cc575b505190835b825181101561218157611f348184614a11565b5151611f3f81615143565b611f4881615143565b600181036120095750602080611f5e8386614a11565b510151906040828051810103126105f657611f7c6040918301615163565b91015190818611611fe057868080936001600160a01b038294166204baf0f1611fa36148c6565b5015611fb757611fb2906149ec565b611f21565b866040517fe373ab5c000000000000000000000000000000000000000000000000000000008152fd5b886040517f644f3cdc000000000000000000000000000000000000000000000000000000008152fd5b9061201382615143565b60029180830361213f575060208061202b8387614a11565b51015192606090818580518101031261213b57612049838601615163565b916040860151950151946024351515908161212e575b5061210557826120dc868061128b9560406120cd8f6120a3611fb29d8a855195869461208a866144b4565b80865260243581526101c6809d52200154602435615c7a565b9690946120bb6120b38984614b8e565b60243561548e565b6001600160a01b036024359116615200565b83806120f0575b505050614b8e565b936024358b52526040892001918254614b8e565b6120fd9260243590615200565b3880836120d4565b8a6040517f4cdcfbf9000000000000000000000000000000000000000000000000000000008152fd5b905060243514153861205f565b8880fd5b90915061214b81615143565b61215857611fb2906149ec565b866040517f7f614f45000000000000000000000000000000000000000000000000000000008152fd5b8482876040519081523460208201526001600160a01b036024359216907fb362243af1e2070d7d5bf8d713f2e0fab64203f1b71462afbe20572909788c5e60403392a4600160655580f35b3d91508185823e6121dd82826144d0565b6020818381010312610d8e5780519067ffffffffffffffff82116115075760408282018483010312611507576040519261221684614452565b8282015167ffffffffffffffff811161236957818301601f82868601010112156123695780848401015161224981614564565b9261225760405194856144d0565b818452602084019281860160208460051b838a8a0101010111612365576020818888010101935b60208460051b838a8a0101010185106122ab57505050505090602092918452010151602082015238611f1c565b845167ffffffffffffffff8111612361576040601f1982858c8c010101868b0103011261236157604051906122df82614452565b602081858c8c0101010151600381101561235d578252604081858c8c01010101519067ffffffffffffffff821161235d57858a018b8b01860182018301603f01121561235d57898b01850101016020818101519093849384939192909161234c91898e01916040016150da565b83820152815201950194905061227e565b8e80fd5b8c80fd5b8a80fd5b8780fd5b91509161239a877f0000000000000000000000000000000000000000000000000000000000000000615130565b9485810390811161241057948680808084866201adb0f16123b96148c6565b50156123c9575050818591611ea5565b604080517f4b789d360000000000000000000000000000000000000000000000000000000081526001600160a01b03909316838b0190815260208101929092528291010390fd5b60248760118b634e487b7160e01b835252fd5b50346105fa57600319606081360112610a8a5761243e6143b0565b60249067ffffffffffffffff82358181116105f65761246090369087016146a0565b604496919692833590811161213b5761247c90369084016146a0565b976001600160a01b0392838716963388141580612771575b61272b57506124b192916124a991369161457c565b98369161457c565b9584156126c3576124c58851885114614b9b565b604051916124d2836144b4565b8983526101cb54169182612600575b505050865b8787518210156125b657506124fb8188614a11565b516125068288614a11565b5190808a52609760209080825260408c2088600052825260406000205492848410612550578c5281526040808c20600089815292529020919003905561254b906149ec565b6124e6565b6084877f455243313135353a206275726e20616d6f756e7420657863656564732062616c8a8d876040519462461bcd60e51b8652850152808401528201527f616e6365000000000000000000000000000000000000000000000000000000006064820152fd5b8085897f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb6125ec8b604051918291339583614c0c565b0390a4806040516125fc816144b4565b5280f35b823b156126be5785928760008661268d82968a968f8f61266e61267e926040519d8e9c8d9b8c9a7f80b10ace000000000000000000000000000000000000000000000000000000008c5230908c015233908b015289015288606489015260e0608489015260e48801906145e5565b90848783030160a48801526145e5565b918483030160c48501526143ff565b03925af180156126b2576126a3575b80806124e1565b6126ac906144a0565b3861269c565b6040513d6000823e3d90fd5b600080fd5b6084837f455243313135353a206275726e2066726f6d20746865207a65726f20616464728660238a60206040519562461bcd60e51b87528601528401528201527f65737300000000000000000000000000000000000000000000000000000000006064820152fd5b604080517f839c23f2000000000000000000000000000000000000000000000000000000008152338189019081526001600160a01b039093166020840152918291010390fd5b50878c52609860205260408c203360005260205260ff6040600020541615612494565b50346105fa5760206003193601126105fa5760406020926001600160a01b03923581526101c78452205416604051908152f35b8234610639576127ed6127d9366146d1565b6127e68394929433615022565b8383615ae1565b7f0000000000000000000000000000000000000000000000000000000000000000809114918261294d575b826128f4575b50506128275780f35b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060406101c980549073ffffffffffffffffffffffffffffffffffffffff19821690556001600160a01b0382519116815260006020820152a160006040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f339180611cce819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b61294592507f0000000000000000000000000000000000000000000000000000000000000000916000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b15828061281e565b6101c9546001600160a01b038083169116149250612818565b5090346106395760c06003193601126106395767ffffffffffffffff8235818111610a8a576129989036908501614546565b906129a236614619565b6001600160a01b0360843516608435036126be5760a435828111610d8e576129cd90369087016146a0565b9190926129d8614ebe565b85549460ff8660081c161595868097612e20575b8015612e09575b15612d9f5786600160ff198316178955612d71575b50612a2b60ff885460081c16612a1d81614e4d565b612a2681614e4d565b614e4d565b6001606555612a867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03608435167f0000000000000000000000000000000000000000000000000000000000000000615a7d565b6101c89182549260018401905560405191612aa083614484565b82526000602083015260006040830152826000526101c66020526040600020908251998a519182116110b15750612ad78254614d6e565b601f8111612d2d575b506020601f8211600114612cbd578190612b819798999a9b600092612cb2575b50506000198260011b9260031b1c19161781555b60208201516001820155600260408301519101557f5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe60405180612b583394826146fb565b0390a37f0000000000000000000000000000000000000000000000000000000000000000615ced565b612b956001600160a01b0360843516615905565b612ba06084356159e0565b80612c0b575b5050612bb5575b600160655580f35b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff81541681557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a1612bad565b612c5f91612c5a7f0000000000000000000000000000000000000000000000000000000000000000337f0000000000000000000000000000000000000000000000000000000000000000615a7d565b615dfa565b50612cab7f0000000000000000000000000000000000000000000000000000000000000000337f0000000000000000000000000000000000000000000000000000000000000000615ae1565b3880612ba6565b015190503880612b00565b8260005260206000209a60005b601f1984168110612d1557509a8291612b8198999a9b9c83601f196001961610612cfc575b505050811b018155612b14565b015160001960f88460031b161c19169055388080612cef565b828201518d556001909c019b60209283019201612cca565b826000526020600020601f830160051c810160208410612d6a575b601f830160051c82018110612d5e575050612ae0565b60008155600101612d48565b5080612d48565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001661010117875538612a08565b60848960206040519162461bcd60e51b8352820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152fd5b50303b1580156129f35750600160ff8216146129f3565b50600160ff8216106129ec565b509034610639578060031936011261063957506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612e9a5760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b60849060206040519162461bcd60e51b8352820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152fd5b5060406003193601126105fa57612f196143b0565b60243567ffffffffffffffff8111610a8657612f389036908401614546565b6001600160a01b0390817f00000000000000000000000000000000000000000000000000000000000000001691612f718330141561472a565b612fa07f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc93828554161461479b565b612fca7f000000000000000000000000000000000000000000000000000000000000000033615022565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615613001575050506116e9915061480c565b8391929316604051937f52d1902d00000000000000000000000000000000000000000000000000000000855260209485818881865afa60009181613213575b506130ae57608487876040519162461bcd60e51b8352820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152fd5b959192949395036131aa576130c28461480c565b604051917fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a28451158015906131a2575b613103575b505050505080f35b833b1561313d57505082600092839261313295519201905af46131246148c6565b61312c6148f6565b91614d1b565b5038808080806130fb565b9160849262461bcd60e51b8352820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e747261637400000000000000000000000000000000000000000000000000006064820152fd5b5060016130f6565b608490836040519162461bcd60e51b8352820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152fd5b90918782813d831161323b575b61322a81836144d0565b810103126106395750519038613040565b503d613220565b50346105fa5760406003193601126105fa5767ffffffffffffffff908035828111610a865736602382011215610a8657808201359261328084614564565b9161328e60405193846144d0565b84835260209460248685019160051b8301019136831161236957602401905b8282106133d257505050602435908111610d8e576132ce90369084016145ca565b9181518351036133695750805193601f196133016132eb87614564565b966132f960405198896144d0565b808852614564565b0136858701375b8151811015613352578061333d6001600160a01b0361332a61334d9486614a11565b51166133368387614a11565b5190614955565b6133478288614a11565b526149ec565b613308565b505050610b136040519282849384528301906145e5565b608490846040519162461bcd60e51b8352820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d6174636800000000000000000000000000000000000000000000006064820152fd5b81356001600160a01b03811681036126be5781529086019086016132ad565b5090346106395760406003193601126106395760406001600160a01b03916134176143c6565b933581526101fe6020522091166000526020526020604060002054604051908152f35b50346105fa57816003193601126105fa576134967f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000033614f13565b476001600160a01b036101ca8480808086868654166204baf0f16134b86148c6565b50156134c2578480f35b604494505416604051927fa489930c0000000000000000000000000000000000000000000000000000000084528301526024820152fd5b50346105fa57602080600319360112610a8a576135146143b0565b906001600160a01b03807f00000000000000000000000000000000000000000000000000000000000000001661354c8130141561472a565b61357b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc91838354161461479b565b6135a57f000000000000000000000000000000000000000000000000000000000000000033615022565b604051916135b2836144b4565b8683527f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156135ed57505050506116e9915061480c565b8492939416906040517f52d1902d00000000000000000000000000000000000000000000000000000000815285818881865afa600091816136f2575b5061369757608487876040519162461bcd60e51b8352820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152fd5b959192949395036131aa576136ab8461480c565b604051917fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a28451158015906136ea5761310357505050505080f35b5060006130f6565b90918782813d831161371a575b61370981836144d0565b810103126106395750519038613629565b503d6136ff565b50346105fa576003199060a082360112610a8a5761373d6143b0565b916137466143c6565b9267ffffffffffffffff926044358481116105f65761376890369083016145ca565b906064358581116123695761378090369083016145ca565b94608435908111612369576137989036908301614546565b93336001600160a01b0385161480156139ee575b6137b590614a3b565b6137c28351875114614b9b565b6001600160a01b038716946137d8861515614aac565b6137e68188868b89336155f5565b885b845181101561388257806137ff61387d9287614a11565b518b61380b838c614a11565b5191808252609790602092828452604081206001600160a01b038d1660005284528460406000205461383f82821015614b1d565b8383528486528d6001600160a01b0360408520911660005286520360406000205552815260408d20908a6000525261128b6040600020918254614b8e565b6137e8565b5090949395929196846040516001600160a01b038916907f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb3391806138c88a8a83614c0c565b0390a43b6138d4578780f35b60405194859384937fbc197c810000000000000000000000000000000000000000000000000000000098898652338b8701526001600160a01b031660248601526044850160a0905260a48501613929916145e5565b8285820301606486015261393c916145e5565b9083820301608484015261394f916143ff565b03815a602094600091f1600091816139ce575b506139a15750506001613973614c69565b6308c379a01461398e575b6104535750388080808080808780f35b613996614c87565b80611497575061397e565b7fffffffff00000000000000000000000000000000000000000000000000000000160361052d5750610448565b6139e791925060203d81116105c8576105b981836144d0565b9038613962565b506001600160a01b0384168852609860205260408820336000526020526137b560ff6040600020541690506137ac565b50346105fa5760406003193601126105fa57613a3a9035615b9c565b6001600160a01b036040613a84613a5d60243563ffffffff602087015116615130565b7f000000000000000000000000000000000000000000000000000000000000000090615c5a565b92015116610b1360405192839283602090939291936001600160a01b0360408201951681520152565b8234610639576060600319360112610639576020613b1f613acc6143b0565b6044357f000000000000000000000000000000000000000000000000000000000000000017906024356000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b6040519015158152f35b5090346106395760406003193601126106395781359167ffffffffffffffff602435818111610a8657613b5f9036908401614546565b93613b8b7f00000000000000000000000000000000000000000000000000000000000000008233614f13565b7f00000000000000000000000000000000000000000000000000000000000000008114613d095760405190807f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b60209384815280613beb8682018b6143ff565b0390a284526101c6815260408420928551928311613cf65750613c0e8354614d6e565b601f8111613cb3575b5080601f8311600114613c515750839482939492613c46575b50506000198260011b9260031b1c191617905580f35b015190503880613c30565b90601f198316958486528286209286905b888210613c9b57505083600195969710613c82575b505050811b01905580f35b015160001960f88460031b161c19169055388080613c77565b80600185968294968601518155019501930190613c62565b838552818520601f840160051c810191838510613cec575b601f0160051c01905b818110613ce15750613c17565b858155600101613cd4565b9091508190613ccb565b846041602492634e487b7160e01b835252fd5b826040517f4e34a9e2000000000000000000000000000000000000000000000000000000008152fd5b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346105fa5760606003193601126105fa578035602435916001600160a01b038316809303610a865767ffffffffffffffff9060443582811161150757613db79036908301614424565b9290613dc1614ebe565b613dec7f00000000000000000000000000000000000000000000000000000000000000008633614f13565b85613eb9575050505080835261012d6020526040832073ffffffffffffffffffffffffffffffffffffffff1981541690555b6040513383837f5010f780a0de79bcfb9f3d6fec3cfe29758ef5c5800d575af709bc590bd78ade8780a481613e8257505060207f56e810c8cae84731149f628981d25769a084570b9ba6eebf3c32879e3dce560991604051908152a1600160655580f35b7f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b91925080602060409252846020820152a2612bad565b84875261012d602052604087208673ffffffffffffffffffffffffffffffffffffffff198254161790556040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f7bc7e64600000000000000000000000000000000000000000000000000000000848201526020816024818a5afa90811561402e578891614010575b5015613fe0578690863b156105fa57613f939460405195869283927f9ded06df000000000000000000000000000000000000000000000000000000008452602088850152602484019161510f565b038183895af18015613fd557613fac575b505050613e1e565b8295939511613fc2575060405291388080613fa4565b826041602492634e487b7160e01b835252fd5b6040513d88823e3d90fd5b60248387604051917fda755beb000000000000000000000000000000000000000000000000000000008352820152fd5b614028915060203d8111610d7c57610d6e81836144d0565b38613f45565b6040513d8a823e3d90fd5b50346105fa5760206003193601126105fa576140536143b0565b906140cf7f00000000000000000000000000000000000000000000000000000000000000006140828133615022565b837f0000000000000000000000000000000000000000000000000000000000000000916000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b156140de57506116e990615905565b6040517f98ee9d38000000000000000000000000000000000000000000000000000000008152fd5b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b8234610639576020600319360112610639576116e961415e6143b0565b6141a97f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000033614f13565b6159e0565b50903461063957602060031936011261063957610b13610aff833561586e565b82346106395780600319360112610639576040519080610193908154906141f482614d6e565b80865292600192808416908115614278575060011461421e575b610b1386610aff818803826144d0565b815292507ffc8af01f449989052b52093a58fc9f42d0b11f0c6dd5dca0463dab62346ccc685b828410614260575050508101602001610aff82610b138561420e565b80546020858701810191909152909301928101614244565b879650610b1397945060209350610aff95925060ff1991501682840152151560051b82010192938561420e565b50346105fa5760206003193601126105fa57357fffffffff0000000000000000000000000000000000000000000000000000000081168091036105fa57807f2a55205a000000000000000000000000000000000000000000000000000000006020921490811561431b575b506040519015158152f35b7f6467a6fc0000000000000000000000000000000000000000000000000000000091501482614310565b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b82346106395760406003193601126106395760206143a861439f6143b0565b60243590614955565b604051908152f35b600435906001600160a01b03821682036126be57565b602435906001600160a01b03821682036126be57565b60005b8381106143ef5750506000910152565b81810151838201526020016143df565b90601f19601f60209361441d815180928187528780880191016143dc565b0116010190565b9181601f840112156126be5782359167ffffffffffffffff83116126be57602083818601950101116126be57565b6040810190811067ffffffffffffffff82111761446e57604052565b634e487b7160e01b600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761446e57604052565b67ffffffffffffffff811161446e57604052565b6020810190811067ffffffffffffffff82111761446e57604052565b90601f601f19910116810190811067ffffffffffffffff82111761446e57604052565b67ffffffffffffffff811161446e57601f01601f191660200190565b92919261451b826144f3565b9161452960405193846144d0565b8294818452818301116126be578281602093846000960137010152565b9080601f830112156126be578160206145619335910161450f565b90565b67ffffffffffffffff811161446e5760051b60200190565b929161458782614564565b9161459560405193846144d0565b829481845260208094019160051b81019283116126be57905b8282106145bb5750505050565b813581529083019083016145ae565b9080601f830112156126be578160206145619335910161457c565b90815180825260208080930193019160005b828110614605575050505090565b8351855293810193928101926001016145f7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc60609101126126be57604051906060820182811067ffffffffffffffff82111761446e576040528163ffffffff60243581811681036126be57825260443590811681036126be576020820152606435906001600160a01b03821682036126be5760400152565b9181601f840112156126be5782359167ffffffffffffffff83116126be576020808501948460051b0101116126be57565b60031960609101126126be57600435906024356001600160a01b03811681036126be579060443590565b6020815260606040614718845183602086015260808501906143ff565b93602081015182850152015191015290565b1561473157565b608460405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152fd5b156147a257565b608460405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152fd5b803b1561485c576001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc911673ffffffffffffffffffffffffffffffffffffffff19825416179055565b608460405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152fd5b3d156148f1573d906148d7826144f3565b916148e560405193846144d0565b82523d6000602084013e565b606090565b6040519061490382614484565b602782527f206661696c6564000000000000000000000000000000000000000000000000006040837f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c60208201520152565b6001600160a01b031690811561498257600052609760205260406000209060005260205260406000205490565b608460405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201527f616c6964206f776e6572000000000000000000000000000000000000000000006064820152fd5b60001981146149fb5760010190565b634e487b7160e01b600052601160045260246000fd5b8051821015614a255760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b15614a4257565b608460405162461bcd60e51b815260206004820152602e60248201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60448201527f6572206f7220617070726f7665640000000000000000000000000000000000006064820152fd5b15614ab357565b608460405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152fd5b15614b2457565b608460405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201527f72207472616e73666572000000000000000000000000000000000000000000006064820152fd5b919082018092116149fb57565b15614ba257565b608460405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d617463680000000000000000000000000000000000000000000000006064820152fd5b9091614c23614561936040845260408401906145e5565b9160208184039101526145e5565b908160209103126126be57517fffffffff00000000000000000000000000000000000000000000000000000000811681036126be5790565b60009060033d11614c7657565b905060046000803e60005160e01c90565b600060443d106145615760405160031991823d016004833e815167ffffffffffffffff918282113d602484011117614ce557818401948551938411614ced573d85010160208487010111614ce55750614561929101602001906144d0565b949350505050565b50949350505050565b60405190614d0382614452565b60018252602082016020368237825115614a25575290565b909160609115614d2a57505090565b614d35919392614d37565b565b805190925015614d4a5750805190602001fd5b6104c69060405191829162461bcd60e51b83526020600484015260248301906143ff565b90600182811c92168015614d9e575b6020831014614d8857565b634e487b7160e01b600052602260045260246000fd5b91607f1691614d7d565b9060405191826000825492614dbc84614d6e565b908184526001948581169081600014614e295750600114614de6575b5050614d35925003836144d0565b9093915060005260209081600020936000915b818310614e11575050614d3593508201013880614dd8565b85548884018501529485019487945091830191614df9565b9050614d3595506020935060ff1991501682840152151560051b8201013880614dd8565b15614e5457565b608460405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152fd5b600260655414614ecf576002606555565b606460405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b90917f0000000000000000000000000000000000000000000000000000000000000000614f6882821784866000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b908115614fcb575b5015614f7b57505050565b6104c6906040519384937f4baa2a4d000000000000000000000000000000000000000000000000000000008552600485016040919493926001600160a01b03606083019616825260208201520152565b61501c9150837f00000000000000000000000000000000000000000000000000000000000000006000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b38614f70565b7f00000000000000000000000000000000000000000000000000000000000000006150738183856000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b8015615084575b15614f7b57505050565b506150d581837f00000000000000000000000000000000000000000000000000000000000000006000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b61507a565b909291926150e7816144f3565b916150f560405193846144d0565b8294828452828201116126be576020614d359301906143dc565b601f8260209493601f19938186528686013760008582860101520116010190565b818102929181159184041417156149fb57565b6003111561514d57565b634e487b7160e01b600052602160045260246000fd5b51906001600160a01b03821682036126be57565b908160209103126126be575180151581036126be5790565b1561519657565b608460405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152fd5b9291906001600160a01b03841661521881151561518f565b6152368461522584614cf6565b61522e86614cf6565b90883361552a565b60009282845260209460978652604096878620848752875287862061525c848254614b8e565b905583868951878152858a8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628b3392a43b61529e575b50505050505050565b6152f99286928689518096819582947ff23a6e61000000000000000000000000000000000000000000000000000000009a8b85523360048601528560248601526044850152606484015260a0608484015260a48301906143ff565b03925af183918161546f575b506153d5575050600191615317614c69565b6308c379a01461539f575b505061533657505b38808080808080615295565b5162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d4552433131353560448201527f526563656976657220696d706c656d656e7465720000000000000000000000006064820152608490fd5b6153a7614c87565b91826153b35750615322565b846104c691505192839262461bcd60e51b8452600484015260248301906143ff565b7fffffffff00000000000000000000000000000000000000000000000000000000160391506154069050575061532a565b5162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a6563746560448201527f6420746f6b656e730000000000000000000000000000000000000000000000006064820152608490fd5b615487919250853d87116105c8576105b981836144d0565b9038615305565b90816000526101c66020526040600020906040516154ab81614484565b6154b483614da8565b81526154d88260406002600187015496602086019788520154930192808452614b8e565b92518093116154e75750505050565b608494505190604051937f1255c8fd0000000000000000000000000000000000000000000000000000000085526004850152602484015260448301526064820152fd5b9091926001600160a01b0394856101cb5416928361554b5750505050505050565b833b156126be576155cc87936000979361267e6155b98a966040519c8d9b8c9a8b997f80b10ace000000000000000000000000000000000000000000000000000000008b523060048c01521660248a01528960448a015216606488015260e0608488015260e48701906145e5565b60031993848783030160a48801526145e5565b03925af180156126b2576155e6575b808080808080615295565b6155ef906144a0565b386155db565b9490926001600160a01b0395866101cb54169384615618575b5050505050505050565b843b156126be57600096889461267e6155b98a9688615688966040519e8f9d8e9c8d9b7f80b10ace000000000000000000000000000000000000000000000000000000008d528c6004309101521660248c01521660448a015216606488015260e0608488015260e48701906145e5565b03925af180156126b2576156a3575b8080808080808061560e565b6156ac906144a0565b38615697565b6020818303126126be5780519067ffffffffffffffff82116126be57019080601f830112156126be578151614561926020016150da565b6001600160a01b0361571a7f0000000000000000000000000000000000000000000000000000000000000000615b47565b16806157295750614561615787565b6000600491604051928380927fe8a3d4850000000000000000000000000000000000000000000000000000000082525afa9081156126b25760009161576c575090565b614561913d8091833e61577f81836144d0565b8101906156b2565b60008080526101c690816020526040916157a383832054614d6e565b61585e575080805261012d6020526001600160a01b039080828482205416801561582d575b60248551809581937f0e89341c000000000000000000000000000000000000000000000000000000008352856004840152165afa9283156158235750809261580f57505090565b61456192503d8091833e61577f81836144d0565b51903d90823e3d90fd5b50507f00000000000000000000000000000000000000000000000000000000000000008152808284822054166157c8565b8180526020522061456190614da8565b6000908082526101c6806020526158886040842054614d6e565b6158f25750816001600160a01b0361589f83615b47565b16916024604051809481937f0e89341c00000000000000000000000000000000000000000000000000000000835260048301525afa9182156158e657809261580f57505090565b604051903d90823e3d90fd5b9161456192604092825260205220614da8565b6101c980546001600160a01b0392831673ffffffffffffffffffffffffffffffffffffffff19821681179092556040805193909116835260208301919091527f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a160006040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f3391806159db819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b0390a3565b6001600160a01b036101ca911673ffffffffffffffffffffffffffffffffffffffff1982541617905560016040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f3391806159db819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b7f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca60008281526101fe94856020526001600160a01b0360408320951694858352602052604082205417948382526020526040812084825260205284604082205580a4565b7f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca60008281526101fe94856020526001600160a01b03604083209516948583526020526040822054901916948382526020526040812084825260205284604082205580a4565b60005261012d6020526001600160a01b03908160406000205416918215615b6b5750565b9091507f00000000000000000000000000000000000000000000000000000000000000006000526040600020541690565b6040805191615baa83614484565b60009081845281836020958287820152015281526101609081845282812090835191615bd583614484565b549263ffffffff9283851681528385881c16878201526001600160a01b038095871c168087830152615c5057507f00000000000000000000000000000000000000000000000000000000000000008252855283902083519490615c3786614484565b5491808316865282821c1690850152821c169082015290565b9550505050505090565b8115615c64570490565b634e487b7160e01b600052601260045260246000fd5b615c8690939293615b9c565b9263ffffffff9182855116908115615cd45790615ca592910690614b8e565b9060001981855116018181116149fb576001600160a01b0392604092615ccc921690615c5a565b930151169190565b505050509060406001600160a01b039101511690600090565b63ffffffff60018184511614615dd0578160005261016060205260406000209083511681549067ffffffff00000000602086015160201b16907fffffffff000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffff0000000000000000604088015160401b16931617171790557f5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d604051806159db33958291909160406001600160a01b0381606084019563ffffffff8082511686526020820151166020860152015116910152565b60046040517f0d9b92f1000000000000000000000000000000000000000000000000000000008152fd5b9190615e0581614564565b90615e1360405192836144d0565b808252601f19615e2282614564565b0160005b818110615eec575050819360005b828110615e415750505050565b8060051b8201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1833603018112156126be5782019081359167ffffffffffffffff83116126be5760208091019083360382136126be57600080615ead615ecc94615ee797369161450f565b615eb56148f6565b9381519101305af4615ec56148c6565b9030615efd565b615ed68287614a11565b52615ee18186614a11565b506149ec565b615e34565b806060602080938701015201615e26565b919260609115615f61575050815115615f14575090565b3b15615f1d5790565b606460405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b909392614d359250614d3756fea26469706673582212200891e324b33d842d5ea9926e249cee81b1b76d106003f0c8e06b0e0b7cc5c91f64736f6c634300081100330000000000000000000000000000000000000000000000000002c2ad68fd9000000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d0
Deployed Bytecode
0x608060405260048036101561001357600080fd5b600090813560e01c8062fdd58e14614380578063011442011461434557806301ffc9a7146142a557806306fdde03146141ce5780630e89341c146141ae57806310a7eb5d1461414157806313966db51461410657806313af40351461403957806316680fad14613d6d57806318711c7d14613d3257806318e97fd114613b2957806323bd038614613aad5780632a55205a14613a1e5780632eb2c2d614613721578063300ecdb9146133f15780633659cfe6146134f95780633ccfd60b1461343a5780634913162d146133f15780634e1273f4146132425780634f1ef28614612f0457806352d1902d14612e2d5780635b2f6347146129665780635d0f6cba146127c757806369a5b302146127945780636b20c45414612423578063731133e914611df657806375794a3c14611dd7578063765b0c3614611d935780637f2dc61c14611be35780637f77f57414611b955780638621ea4b14611b545780638c7a63ae14611ae15780638da5cb5b14611ab95780638ec998a014611a97578063929a712814611a5c57806395d89b41146119fe5780639c5c63c914611933578063a0a8e460146118d5578063a22cb465146117dd578063a453eaf0146117a2578063ac9650d8146116ec578063afed7e9e14611698578063bb3bafd614611640578063c046435614611605578063c238d1ee1461150b578063d1ad846b146110c6578063d258609a14610d92578063d904b94a14610bd7578063dd15e05f14610ba4578063e72878b414610b47578063e74d86c214610b17578063e8a3d48514610ae3578063e985e9c514610a8e578063ef71c82e1461063c578063f1b0d6bb146105fe5763f242432a1461028657600080fd5b346105fa5760a06003193601126105fa5761029f6143b0565b6102a76143c6565b90604435906064359060843567ffffffffffffffff81116105f6576102cf9036908701614546565b916001600160a01b039161031c848483169433861480156105cf575b6102f490614a3b565b881692610302841515614aac565b61030b88614cf6565b8961031587614cf6565b92336155f5565b84885260209560978752604089208460005287528260406000205461034382821015614b1d565b878b526097895260408b20866000528952036040600020558589526097875260408920826000528752604060002061037c848254614b8e565b90558184604051888152858a8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6260403392a43b6103ba578780f35b869460008794610417604051978896879586947ff23a6e61000000000000000000000000000000000000000000000000000000009c8d8752339087015260248601526044850152606484015260a0608484015260a48301906143ff565b03925af1600091816105a0575b506104fe575050600190610436614c69565b6308c379a0146104ca575b5061045357505b388080808080808780f35b6104c69060405191829162461bcd60e51b8352820160809060208152603460208201527f455243313135353a207472616e7366657220746f206e6f6e2d4552433131353560408201527f526563656976657220696d706c656d656e74657200000000000000000000000060608201520190565b0390fd5b6104d2614c87565b806104dd5750610441565b6104c6849160405193849362461bcd60e51b855284015260248301906143ff565b7fffffffff000000000000000000000000000000000000000000000000000000001603905061052d5750610448565b6104c69060405191829162461bcd60e51b8352820160809060208152602860208201527f455243313135353a204552433131353552656365697665722072656a6563746560408201527f6420746f6b656e7300000000000000000000000000000000000000000000000060608201520190565b6105c1919250843d86116105c8575b6105b981836144d0565b810190614c31565b9038610424565b503d6105af565b50858b52609860205260408b20336000526020526102f460ff6040600020541690506102eb565b8680fd5b5080fd5b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000048152f35b80fd5b5090346106395760406003193601126106395767ffffffffffffffff918035838111610a8a5761066f9036908301614546565b602435848111610a86576106869036908401614546565b917f0000000000000000000000000000000000000000000000000000000000000010947f000000000000000000000000000000000000000000000000000000000000000295600080526020966101fe88526040600020336000528852818117604060002054161590811591610a2f575b50156109f157507f000000000000000000000000000000000000000000000000000000000000000085526101c6865260408520918351928284116109de5761073e8154614d6e565b93601f9485811161099e575b50808986821160011461093f578991610934575b506000198260011b9260031b1c19161790555b84519182116109215750610193916107898354614d6e565b8181116108c3575b508690821160011461081a57956107fa9392826108099388997f74b7c2afa3f89c562b59674a101e2c48bceeb27cdb620afefa14446f1ffa487b98999161080f575b506000198260011b9260031b1c19161790555b6040519384936040855260408501906143ff565b908382039084015233956143ff565b0390a280f35b9050880151386107d3565b8286527ffc8af01f449989052b52093a58fc9f42d0b11f0c6dd5dca0463dab62346ccc6890601f198316875b8181106108ac5750837f74b7c2afa3f89c562b59674a101e2c48bceeb27cdb620afefa14446f1ffa487b979899936107fa9796936108099660019410610893575b5050811b0190556107e6565b8a015160001960f88460031b161c191690553880610887565b91928960018192868b015181550194019201610846565b8387527ffc8af01f449989052b52093a58fc9f42d0b11f0c6dd5dca0463dab62346ccc688280850160051c8201928a8610610918575b0160051c01905b81811061090d5750610791565b878155600101610900565b925081926108f9565b856041602492634e487b7160e01b835252fd5b90508601513861075e565b838a528a8a2091601f19168a5b8c828210610988575050908360019493921061096f575b5050811b019055610771565b88015160001960f88460031b161c191690553880610963565b600184958293958d01518155019401920161094c565b8289528989208680840160051c8201928c85106109d5575b0160051c01905b8181106109ca575061074a565b8981556001016109bd565b925081926109b6565b602487604184634e487b7160e01b835252fd5b82606491604051917f4baa2a4d0000000000000000000000000000000000000000000000000000000083523390830152600060248301526044820152fd5b610a809150337f00000000000000000000000000000000000000000000000000000000000000006000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b386106f6565b8380fd5b8280fd5b823461063957604060031936011261063957610aa86143b0565b6040610ab26143c6565b926001600160a01b0380931681526098602052209116600052602052602060ff604060002054166040519015158152f35b8234610639578060031936011261063957610b13610aff6156e9565b6040519182916020835260208301906143ff565b0390f35b509034610639576020600319360112610639576020610b368335615b47565b6001600160a01b0360405191168152f35b50346105fa5760206003193601126105fa5780356000196101c8540190808203610b6f578380f35b60449350604051927f4fa09b3f0000000000000000000000000000000000000000000000000000000084528301526024820152fd5b50346105fa5760206003193601126105fa5760406020926001600160a01b039235815261012d8452205416604051908152f35b50346105fa5760606003193601126105fa578035610bf36143c6565b9060443567ffffffffffffffff8111610d8e576001600160a01b03610c1e610c749236908701614546565b93610c4a7f00000000000000000000000000000000000000000000000000000000000000088533614f13565b16917f00000000000000000000000000000000000000000000000000000000000000049083614f13565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f6890e5b30000000000000000000000000000000000000000000000000000000084820152602081602481855afa908115610d83578591610d55575b5015610d2557818492918360208194519301915af1610cf36148c6565b5015610cfd575080f35b6040517fd663a084000000000000000000000000000000000000000000000000000000008152fd5b82602491604051917fe15b8e06000000000000000000000000000000000000000000000000000000008352820152fd5b610d76915060203d8111610d7c575b610d6e81836144d0565b810190615177565b38610cd6565b503d610d64565b6040513d87823e3d90fd5b8480fd5b50903461063957604060031936011261063957813567ffffffffffffffff918282116106395750610dc69036908401614546565b602435610e147f00000000000000000000000000000000000000000000000000000000000000047f000000000000000000000000000000000000000000000000000000000000000033614f13565b610e1c614ebe565b6101c8908154926001928385019055604051610e3781614484565b818152602095868201848152604083019060008252876000526101c6895260406000209284519a8b519182116110b15750610e728454614d6e565b601f811161106c575b5087899a9b60009a98999a508c90601f8411600114610fc157927f1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc0689897959281808c999794600297600093610fb4575b505060001991921b9260031b1c19161784555b518a840155519101557f5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe60405180610f173394826146fb565b0390a3610f457f00000000000000000000000000000000000000000000000000000000000000023385615a7d565b8051610f77575b610f61604051916040835260408301906143ff565b93878201528033940390a3606555604051908152f35b827f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b60405189815280610fac8b8201866143ff565b0390a2610f4c565b0151915060001938610ecb565b908d91601f19859495168860005283600020936000905b82821061103d575050926002959285927f1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc0689c9b99968e9b999610611024575b505050811b018455610ede565b015160001960f88460031b161c19169055388080611017565b92948392949790839297999a9b9c9d9e508887015181550196019401918e9b9a9998979694928e969492610fd8565b846000528a600020601f830160051c8101918c84106110a7575b601f0160051c01905b81811061109c5750610e7b565b60008155890161108f565b9091508190611086565b604190634e487b7160e01b6000525260246000fd5b50346105fa5760031990608082360112610a8a576110e26143b0565b9067ffffffffffffffff6024358181116115075761110390369084016145ca565b926044358281116105f65761111b90369085016145ca565b916064359081116105f6576111369095939536908701614546565b9261113f614ebe565b7f0000000000000000000000000000000000000000000000000000000000000004966111d3887f000000000000000000000000000000000000000000000000000000000000000217337f00000000000000000000000000000000000000000000000000000000000000006000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b1594815b875181101561120d576111ee90876111f3576149ec565b6111d7565b6112088b611201838c614a11565b5133614f13565b6149ec565b5090869291886001600160a01b0386169361122985151561518f565b6112368651895114614b9b565b6112438389888a3361552a565b835b888751821015611297579061125d8161129293614a11565b51611268828a614a11565b5187526020609781526040882090896000525261128b6040600020918254614b8e565b90556149ec565b611245565b905086929495939784876040517f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb3391806112d3888b83614c0c565b0390a43b6113cf575b5050505050805b82518110156113c6576112f68184614a11565b51906113028185614a11565b5183526101c660209080825260029384604087200154611322858b614a11565b519061132d92615c7a565b94909161133a8589614a11565b5186611346878d614a11565b519061135191614b8e565b61135a9161548e565b8786868b8215159961128b97611387956113a39c6113a8575b50505050611381908d614a11565b51614b8e565b93611392868a614a11565b518852526040862001918254614b8e565b6112e3565b6113bc946113b591614a11565b5190615200565b868b828f8d611373565b50600160655580f35b849361142b600061143b9561144b602096604051988997889687957fbc197c81000000000000000000000000000000000000000000000000000000009d8e8852339088015287602488015260a0604488015260a48701906145e5565b90838683030160648701526145e5565b908382030160848401528d6143ff565b03925af1600091816114e7575b506114ba5750506001611469614c69565b6308c379a014611484575b61045357505b84808381876112dc565b61148c614c87565b806114975750611474565b826104c660209260405193849362461bcd60e51b855284015260248301906143ff565b7fffffffff00000000000000000000000000000000000000000000000000000000160361052d575061147a565b61150091925060203d81116105c8576105b981836144d0565b9088611458565b8580fd5b50346105fa5760806003193601126105fa57816115266143b0565b602435926044356064359267ffffffffffffffff8411610d8e5761155186936115d195369101614546565b611559614ebe565b6115847f00000000000000000000000000000000000000000000000000000000000000048533614f13565b8386526115c081846115a581600260406101c69c8d60205220015489615c7a565b9790956115bb6115b58a85614b8e565b8361548e565b615200565b8387816115f3575b50505050614b8e565b9183526020526115e960026040842001918254614b8e565b9055600160655580f35b6115fc93615200565b388083876115c8565b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000028152f35b50903461063957602060031936011261063957610b136116608335615b9c565b6040519182918291909160406001600160a01b0381606084019563ffffffff8082511686526020820151166020860152015116910152565b50346105fa5760806003193601126105fa576116e990356116b836614619565b906116e47f00000000000000000000000000000000000000000000000000000000000000208233614f13565b615ced565b80f35b50346105fa5760209081600319360112610a8a57803567ffffffffffffffff8111610a86576117228492611728923691016146a0565b90615dfa565b60405191838301848452825180915260408401948060408360051b870101940192955b8287106117585785850386f35b909192938280611792837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08a6001960301865288516143ff565b960192019601959291909261174b565b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000108152f35b50346105fa5760406003193601126105fa576117f76143b0565b60243590811515809203610a86576001600160a01b03169182331461186b575033835260986020526040832082600052602052604060002060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a380f35b60849060206040519162461bcd60e51b8352820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c6600000000000000000000000000000000000000000000006064820152fd5b8234610639578060031936011261063957610b136040516118f581614452565b600581527f312e302e3000000000000000000000000000000000000000000000000000000060208201526040519182916020835260208301906143ff565b50346105fa5760406003193601126105fa5781602435823567ffffffffffffffff8211610a8a576001600160a01b036119a4611973859436908801614546565b9261199f7f00000000000000000000000000000000000000000000000000000000000000108233614f13565b615b47565b1682602083519301915af16119b76148c6565b90156119c1578280f35b906104c66020926040519384937f4f424e0800000000000000000000000000000000000000000000000000000000855284015260248301906143ff565b823461063957806003193601126106395760405160208082528160605191828183015260005b838110611a46575050601f19601f836000604080968601015201168101030190f35b6080810151858201604001528492508101611a24565b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000208152f35b8234610639576116e9611aa9366146d1565b91611ab48133615022565b615a7d565b823461063957806003193601126106395760206001600160a01b036101c95416604051908152f35b50346105fa5760206003193601126105fa5781604091610b1393838051611b0781614484565b6060815282602082015201523581526101c660205220600260405191611b2c83614484565b611b3581614da8565b83526001810154602084015201546040820152604051918291826146fb565b50346105fa5760606003193601126105fa57611b7890604435906024359035615c7a565b604080516001600160a01b03939093168352602083019190915290f35b50346105fa5760206003193601126105fa5760609160409135815261016060205220546001600160a01b036040519163ffffffff80821684528160201c16602084015260401c166040820152f35b50346105fa5760206003193601126105fa578035906001600160a01b038216809203610a8a57611c337f000000000000000000000000000000000000000000000000000000000000000033615022565b81611cd4575b506101cb9073ffffffffffffffffffffffffffffffffffffffff1982541617905560026040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f339180611cce819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b0390a380f35b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f80b10ace0000000000000000000000000000000000000000000000000000000082820152602081602481865afa908115611d88578491611d6a575b50611c3957602491604051917f17ce9560000000000000000000000000000000000000000000000000000000008352820152fd5b611d82915060203d8111610d7c57610d6e81836144d0565b38611d36565b6040513d86823e3d90fd5b823461063957806003193601126106395760206040516001600160a01b037f000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d0168152f35b823461063957806003193601126106395760206101c854604051908152f35b5090608060031936011261063957611e0c6143b0565b906044359160643567ffffffffffffffff8111610a8a57611e309036908601614424565b611e3b929192614ebe565b611e717f00000000000000000000000000000000000000000000000000000000000000046024356001600160a01b038516614f13565b8334937f000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d0926001600160a01b03841661236d575b611eff935060405193849283927f6890e5b3000000000000000000000000000000000000000000000000000000008452308c85015260243560248501528a604485015288606485015260a0608485015260a484019161510f565b0381836001600160a01b0387165af1908115611d885784916121cc575b505190835b825181101561218157611f348184614a11565b5151611f3f81615143565b611f4881615143565b600181036120095750602080611f5e8386614a11565b510151906040828051810103126105f657611f7c6040918301615163565b91015190818611611fe057868080936001600160a01b038294166204baf0f1611fa36148c6565b5015611fb757611fb2906149ec565b611f21565b866040517fe373ab5c000000000000000000000000000000000000000000000000000000008152fd5b886040517f644f3cdc000000000000000000000000000000000000000000000000000000008152fd5b9061201382615143565b60029180830361213f575060208061202b8387614a11565b51015192606090818580518101031261213b57612049838601615163565b916040860151950151946024351515908161212e575b5061210557826120dc868061128b9560406120cd8f6120a3611fb29d8a855195869461208a866144b4565b80865260243581526101c6809d52200154602435615c7a565b9690946120bb6120b38984614b8e565b60243561548e565b6001600160a01b036024359116615200565b83806120f0575b505050614b8e565b936024358b52526040892001918254614b8e565b6120fd9260243590615200565b3880836120d4565b8a6040517f4cdcfbf9000000000000000000000000000000000000000000000000000000008152fd5b905060243514153861205f565b8880fd5b90915061214b81615143565b61215857611fb2906149ec565b866040517f7f614f45000000000000000000000000000000000000000000000000000000008152fd5b8482876040519081523460208201526001600160a01b036024359216907fb362243af1e2070d7d5bf8d713f2e0fab64203f1b71462afbe20572909788c5e60403392a4600160655580f35b3d91508185823e6121dd82826144d0565b6020818381010312610d8e5780519067ffffffffffffffff82116115075760408282018483010312611507576040519261221684614452565b8282015167ffffffffffffffff811161236957818301601f82868601010112156123695780848401015161224981614564565b9261225760405194856144d0565b818452602084019281860160208460051b838a8a0101010111612365576020818888010101935b60208460051b838a8a0101010185106122ab57505050505090602092918452010151602082015238611f1c565b845167ffffffffffffffff8111612361576040601f1982858c8c010101868b0103011261236157604051906122df82614452565b602081858c8c0101010151600381101561235d578252604081858c8c01010101519067ffffffffffffffff821161235d57858a018b8b01860182018301603f01121561235d57898b01850101016020818101519093849384939192909161234c91898e01916040016150da565b83820152815201950194905061227e565b8e80fd5b8c80fd5b8a80fd5b8780fd5b91509161239a877f0000000000000000000000000000000000000000000000000002c2ad68fd9000615130565b9485810390811161241057948680808084866201adb0f16123b96148c6565b50156123c9575050818591611ea5565b604080517f4b789d360000000000000000000000000000000000000000000000000000000081526001600160a01b03909316838b0190815260208101929092528291010390fd5b60248760118b634e487b7160e01b835252fd5b50346105fa57600319606081360112610a8a5761243e6143b0565b60249067ffffffffffffffff82358181116105f65761246090369087016146a0565b604496919692833590811161213b5761247c90369084016146a0565b976001600160a01b0392838716963388141580612771575b61272b57506124b192916124a991369161457c565b98369161457c565b9584156126c3576124c58851885114614b9b565b604051916124d2836144b4565b8983526101cb54169182612600575b505050865b8787518210156125b657506124fb8188614a11565b516125068288614a11565b5190808a52609760209080825260408c2088600052825260406000205492848410612550578c5281526040808c20600089815292529020919003905561254b906149ec565b6124e6565b6084877f455243313135353a206275726e20616d6f756e7420657863656564732062616c8a8d876040519462461bcd60e51b8652850152808401528201527f616e6365000000000000000000000000000000000000000000000000000000006064820152fd5b8085897f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb6125ec8b604051918291339583614c0c565b0390a4806040516125fc816144b4565b5280f35b823b156126be5785928760008661268d82968a968f8f61266e61267e926040519d8e9c8d9b8c9a7f80b10ace000000000000000000000000000000000000000000000000000000008c5230908c015233908b015289015288606489015260e0608489015260e48801906145e5565b90848783030160a48801526145e5565b918483030160c48501526143ff565b03925af180156126b2576126a3575b80806124e1565b6126ac906144a0565b3861269c565b6040513d6000823e3d90fd5b600080fd5b6084837f455243313135353a206275726e2066726f6d20746865207a65726f20616464728660238a60206040519562461bcd60e51b87528601528401528201527f65737300000000000000000000000000000000000000000000000000000000006064820152fd5b604080517f839c23f2000000000000000000000000000000000000000000000000000000008152338189019081526001600160a01b039093166020840152918291010390fd5b50878c52609860205260408c203360005260205260ff6040600020541615612494565b50346105fa5760206003193601126105fa5760406020926001600160a01b03923581526101c78452205416604051908152f35b8234610639576127ed6127d9366146d1565b6127e68394929433615022565b8383615ae1565b7f0000000000000000000000000000000000000000000000000000000000000000809114918261294d575b826128f4575b50506128275780f35b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060406101c980549073ffffffffffffffffffffffffffffffffffffffff19821690556001600160a01b0382519116815260006020820152a160006040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f339180611cce819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b61294592507f0000000000000000000000000000000000000000000000000000000000000002916000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b15828061281e565b6101c9546001600160a01b038083169116149250612818565b5090346106395760c06003193601126106395767ffffffffffffffff8235818111610a8a576129989036908501614546565b906129a236614619565b6001600160a01b0360843516608435036126be5760a435828111610d8e576129cd90369087016146a0565b9190926129d8614ebe565b85549460ff8660081c161595868097612e20575b8015612e09575b15612d9f5786600160ff198316178955612d71575b50612a2b60ff885460081c16612a1d81614e4d565b612a2681614e4d565b614e4d565b6001606555612a867f00000000000000000000000000000000000000000000000000000000000000026001600160a01b03608435167f0000000000000000000000000000000000000000000000000000000000000000615a7d565b6101c89182549260018401905560405191612aa083614484565b82526000602083015260006040830152826000526101c66020526040600020908251998a519182116110b15750612ad78254614d6e565b601f8111612d2d575b506020601f8211600114612cbd578190612b819798999a9b600092612cb2575b50506000198260011b9260031b1c19161781555b60208201516001820155600260408301519101557f5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe60405180612b583394826146fb565b0390a37f0000000000000000000000000000000000000000000000000000000000000000615ced565b612b956001600160a01b0360843516615905565b612ba06084356159e0565b80612c0b575b5050612bb5575b600160655580f35b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff81541681557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a1612bad565b612c5f91612c5a7f0000000000000000000000000000000000000000000000000000000000000002337f0000000000000000000000000000000000000000000000000000000000000000615a7d565b615dfa565b50612cab7f0000000000000000000000000000000000000000000000000000000000000002337f0000000000000000000000000000000000000000000000000000000000000000615ae1565b3880612ba6565b015190503880612b00565b8260005260206000209a60005b601f1984168110612d1557509a8291612b8198999a9b9c83601f196001961610612cfc575b505050811b018155612b14565b015160001960f88460031b161c19169055388080612cef565b828201518d556001909c019b60209283019201612cca565b826000526020600020601f830160051c810160208410612d6a575b601f830160051c82018110612d5e575050612ae0565b60008155600101612d48565b5080612d48565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001661010117875538612a08565b60848960206040519162461bcd60e51b8352820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152fd5b50303b1580156129f35750600160ff8216146129f3565b50600160ff8216106129ec565b509034610639578060031936011261063957506001600160a01b037f000000000000000000000000d0561aef1d5cd30a1779f01b41b3436027177d9a163003612e9a5760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b60849060206040519162461bcd60e51b8352820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152fd5b5060406003193601126105fa57612f196143b0565b60243567ffffffffffffffff8111610a8657612f389036908401614546565b6001600160a01b0390817f000000000000000000000000d0561aef1d5cd30a1779f01b41b3436027177d9a1691612f718330141561472a565b612fa07f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc93828554161461479b565b612fca7f000000000000000000000000000000000000000000000000000000000000000033615022565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615613001575050506116e9915061480c565b8391929316604051937f52d1902d00000000000000000000000000000000000000000000000000000000855260209485818881865afa60009181613213575b506130ae57608487876040519162461bcd60e51b8352820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152fd5b959192949395036131aa576130c28461480c565b604051917fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a28451158015906131a2575b613103575b505050505080f35b833b1561313d57505082600092839261313295519201905af46131246148c6565b61312c6148f6565b91614d1b565b5038808080806130fb565b9160849262461bcd60e51b8352820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e747261637400000000000000000000000000000000000000000000000000006064820152fd5b5060016130f6565b608490836040519162461bcd60e51b8352820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152fd5b90918782813d831161323b575b61322a81836144d0565b810103126106395750519038613040565b503d613220565b50346105fa5760406003193601126105fa5767ffffffffffffffff908035828111610a865736602382011215610a8657808201359261328084614564565b9161328e60405193846144d0565b84835260209460248685019160051b8301019136831161236957602401905b8282106133d257505050602435908111610d8e576132ce90369084016145ca565b9181518351036133695750805193601f196133016132eb87614564565b966132f960405198896144d0565b808852614564565b0136858701375b8151811015613352578061333d6001600160a01b0361332a61334d9486614a11565b51166133368387614a11565b5190614955565b6133478288614a11565b526149ec565b613308565b505050610b136040519282849384528301906145e5565b608490846040519162461bcd60e51b8352820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d6174636800000000000000000000000000000000000000000000006064820152fd5b81356001600160a01b03811681036126be5781529086019086016132ad565b5090346106395760406003193601126106395760406001600160a01b03916134176143c6565b933581526101fe6020522091166000526020526020604060002054604051908152f35b50346105fa57816003193601126105fa576134967f00000000000000000000000000000000000000000000000000000000000000207f000000000000000000000000000000000000000000000000000000000000000033614f13565b476001600160a01b036101ca8480808086868654166204baf0f16134b86148c6565b50156134c2578480f35b604494505416604051927fa489930c0000000000000000000000000000000000000000000000000000000084528301526024820152fd5b50346105fa57602080600319360112610a8a576135146143b0565b906001600160a01b03807f000000000000000000000000d0561aef1d5cd30a1779f01b41b3436027177d9a1661354c8130141561472a565b61357b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc91838354161461479b565b6135a57f000000000000000000000000000000000000000000000000000000000000000033615022565b604051916135b2836144b4565b8683527f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156135ed57505050506116e9915061480c565b8492939416906040517f52d1902d00000000000000000000000000000000000000000000000000000000815285818881865afa600091816136f2575b5061369757608487876040519162461bcd60e51b8352820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152fd5b959192949395036131aa576136ab8461480c565b604051917fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a28451158015906136ea5761310357505050505080f35b5060006130f6565b90918782813d831161371a575b61370981836144d0565b810103126106395750519038613629565b503d6136ff565b50346105fa576003199060a082360112610a8a5761373d6143b0565b916137466143c6565b9267ffffffffffffffff926044358481116105f65761376890369083016145ca565b906064358581116123695761378090369083016145ca565b94608435908111612369576137989036908301614546565b93336001600160a01b0385161480156139ee575b6137b590614a3b565b6137c28351875114614b9b565b6001600160a01b038716946137d8861515614aac565b6137e68188868b89336155f5565b885b845181101561388257806137ff61387d9287614a11565b518b61380b838c614a11565b5191808252609790602092828452604081206001600160a01b038d1660005284528460406000205461383f82821015614b1d565b8383528486528d6001600160a01b0360408520911660005286520360406000205552815260408d20908a6000525261128b6040600020918254614b8e565b6137e8565b5090949395929196846040516001600160a01b038916907f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb3391806138c88a8a83614c0c565b0390a43b6138d4578780f35b60405194859384937fbc197c810000000000000000000000000000000000000000000000000000000098898652338b8701526001600160a01b031660248601526044850160a0905260a48501613929916145e5565b8285820301606486015261393c916145e5565b9083820301608484015261394f916143ff565b03815a602094600091f1600091816139ce575b506139a15750506001613973614c69565b6308c379a01461398e575b6104535750388080808080808780f35b613996614c87565b80611497575061397e565b7fffffffff00000000000000000000000000000000000000000000000000000000160361052d5750610448565b6139e791925060203d81116105c8576105b981836144d0565b9038613962565b506001600160a01b0384168852609860205260408820336000526020526137b560ff6040600020541690506137ac565b50346105fa5760406003193601126105fa57613a3a9035615b9c565b6001600160a01b036040613a84613a5d60243563ffffffff602087015116615130565b7f000000000000000000000000000000000000000000000000000000000000271090615c5a565b92015116610b1360405192839283602090939291936001600160a01b0360408201951681520152565b8234610639576060600319360112610639576020613b1f613acc6143b0565b6044357f000000000000000000000000000000000000000000000000000000000000000217906024356000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b6040519015158152f35b5090346106395760406003193601126106395781359167ffffffffffffffff602435818111610a8657613b5f9036908401614546565b93613b8b7f00000000000000000000000000000000000000000000000000000000000000108233614f13565b7f00000000000000000000000000000000000000000000000000000000000000008114613d095760405190807f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b60209384815280613beb8682018b6143ff565b0390a284526101c6815260408420928551928311613cf65750613c0e8354614d6e565b601f8111613cb3575b5080601f8311600114613c515750839482939492613c46575b50506000198260011b9260031b1c191617905580f35b015190503880613c30565b90601f198316958486528286209286905b888210613c9b57505083600195969710613c82575b505050811b01905580f35b015160001960f88460031b161c19169055388080613c77565b80600185968294968601518155019501930190613c62565b838552818520601f840160051c810191838510613cec575b601f0160051c01905b818110613ce15750613c17565b858155600101613cd4565b9091508190613ccb565b846041602492634e487b7160e01b835252fd5b826040517f4e34a9e2000000000000000000000000000000000000000000000000000000008152fd5b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000088152f35b50346105fa5760606003193601126105fa578035602435916001600160a01b038316809303610a865767ffffffffffffffff9060443582811161150757613db79036908301614424565b9290613dc1614ebe565b613dec7f00000000000000000000000000000000000000000000000000000000000000108633614f13565b85613eb9575050505080835261012d6020526040832073ffffffffffffffffffffffffffffffffffffffff1981541690555b6040513383837f5010f780a0de79bcfb9f3d6fec3cfe29758ef5c5800d575af709bc590bd78ade8780a481613e8257505060207f56e810c8cae84731149f628981d25769a084570b9ba6eebf3c32879e3dce560991604051908152a1600160655580f35b7f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b91925080602060409252846020820152a2612bad565b84875261012d602052604087208673ffffffffffffffffffffffffffffffffffffffff198254161790556040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f7bc7e64600000000000000000000000000000000000000000000000000000000848201526020816024818a5afa90811561402e578891614010575b5015613fe0578690863b156105fa57613f939460405195869283927f9ded06df000000000000000000000000000000000000000000000000000000008452602088850152602484019161510f565b038183895af18015613fd557613fac575b505050613e1e565b8295939511613fc2575060405291388080613fa4565b826041602492634e487b7160e01b835252fd5b6040513d88823e3d90fd5b60248387604051917fda755beb000000000000000000000000000000000000000000000000000000008352820152fd5b614028915060203d8111610d7c57610d6e81836144d0565b38613f45565b6040513d8a823e3d90fd5b50346105fa5760206003193601126105fa576140536143b0565b906140cf7f00000000000000000000000000000000000000000000000000000000000000006140828133615022565b837f0000000000000000000000000000000000000000000000000000000000000002916000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b156140de57506116e990615905565b6040517f98ee9d38000000000000000000000000000000000000000000000000000000008152fd5b823461063957806003193601126106395760206040517f0000000000000000000000000000000000000000000000000002c2ad68fd90008152f35b8234610639576020600319360112610639576116e961415e6143b0565b6141a97f00000000000000000000000000000000000000000000000000000000000000207f000000000000000000000000000000000000000000000000000000000000000033614f13565b6159e0565b50903461063957602060031936011261063957610b13610aff833561586e565b82346106395780600319360112610639576040519080610193908154906141f482614d6e565b80865292600192808416908115614278575060011461421e575b610b1386610aff818803826144d0565b815292507ffc8af01f449989052b52093a58fc9f42d0b11f0c6dd5dca0463dab62346ccc685b828410614260575050508101602001610aff82610b138561420e565b80546020858701810191909152909301928101614244565b879650610b1397945060209350610aff95925060ff1991501682840152151560051b82010192938561420e565b50346105fa5760206003193601126105fa57357fffffffff0000000000000000000000000000000000000000000000000000000081168091036105fa57807f2a55205a000000000000000000000000000000000000000000000000000000006020921490811561431b575b506040519015158152f35b7f6467a6fc0000000000000000000000000000000000000000000000000000000091501482614310565b823461063957806003193601126106395760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b82346106395760406003193601126106395760206143a861439f6143b0565b60243590614955565b604051908152f35b600435906001600160a01b03821682036126be57565b602435906001600160a01b03821682036126be57565b60005b8381106143ef5750506000910152565b81810151838201526020016143df565b90601f19601f60209361441d815180928187528780880191016143dc565b0116010190565b9181601f840112156126be5782359167ffffffffffffffff83116126be57602083818601950101116126be57565b6040810190811067ffffffffffffffff82111761446e57604052565b634e487b7160e01b600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761446e57604052565b67ffffffffffffffff811161446e57604052565b6020810190811067ffffffffffffffff82111761446e57604052565b90601f601f19910116810190811067ffffffffffffffff82111761446e57604052565b67ffffffffffffffff811161446e57601f01601f191660200190565b92919261451b826144f3565b9161452960405193846144d0565b8294818452818301116126be578281602093846000960137010152565b9080601f830112156126be578160206145619335910161450f565b90565b67ffffffffffffffff811161446e5760051b60200190565b929161458782614564565b9161459560405193846144d0565b829481845260208094019160051b81019283116126be57905b8282106145bb5750505050565b813581529083019083016145ae565b9080601f830112156126be578160206145619335910161457c565b90815180825260208080930193019160005b828110614605575050505090565b8351855293810193928101926001016145f7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc60609101126126be57604051906060820182811067ffffffffffffffff82111761446e576040528163ffffffff60243581811681036126be57825260443590811681036126be576020820152606435906001600160a01b03821682036126be5760400152565b9181601f840112156126be5782359167ffffffffffffffff83116126be576020808501948460051b0101116126be57565b60031960609101126126be57600435906024356001600160a01b03811681036126be579060443590565b6020815260606040614718845183602086015260808501906143ff565b93602081015182850152015191015290565b1561473157565b608460405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152fd5b156147a257565b608460405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152fd5b803b1561485c576001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc911673ffffffffffffffffffffffffffffffffffffffff19825416179055565b608460405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152fd5b3d156148f1573d906148d7826144f3565b916148e560405193846144d0565b82523d6000602084013e565b606090565b6040519061490382614484565b602782527f206661696c6564000000000000000000000000000000000000000000000000006040837f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c60208201520152565b6001600160a01b031690811561498257600052609760205260406000209060005260205260406000205490565b608460405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201527f616c6964206f776e6572000000000000000000000000000000000000000000006064820152fd5b60001981146149fb5760010190565b634e487b7160e01b600052601160045260246000fd5b8051821015614a255760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b15614a4257565b608460405162461bcd60e51b815260206004820152602e60248201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60448201527f6572206f7220617070726f7665640000000000000000000000000000000000006064820152fd5b15614ab357565b608460405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152fd5b15614b2457565b608460405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201527f72207472616e73666572000000000000000000000000000000000000000000006064820152fd5b919082018092116149fb57565b15614ba257565b608460405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d617463680000000000000000000000000000000000000000000000006064820152fd5b9091614c23614561936040845260408401906145e5565b9160208184039101526145e5565b908160209103126126be57517fffffffff00000000000000000000000000000000000000000000000000000000811681036126be5790565b60009060033d11614c7657565b905060046000803e60005160e01c90565b600060443d106145615760405160031991823d016004833e815167ffffffffffffffff918282113d602484011117614ce557818401948551938411614ced573d85010160208487010111614ce55750614561929101602001906144d0565b949350505050565b50949350505050565b60405190614d0382614452565b60018252602082016020368237825115614a25575290565b909160609115614d2a57505090565b614d35919392614d37565b565b805190925015614d4a5750805190602001fd5b6104c69060405191829162461bcd60e51b83526020600484015260248301906143ff565b90600182811c92168015614d9e575b6020831014614d8857565b634e487b7160e01b600052602260045260246000fd5b91607f1691614d7d565b9060405191826000825492614dbc84614d6e565b908184526001948581169081600014614e295750600114614de6575b5050614d35925003836144d0565b9093915060005260209081600020936000915b818310614e11575050614d3593508201013880614dd8565b85548884018501529485019487945091830191614df9565b9050614d3595506020935060ff1991501682840152151560051b8201013880614dd8565b15614e5457565b608460405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152fd5b600260655414614ecf576002606555565b606460405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b90917f0000000000000000000000000000000000000000000000000000000000000002614f6882821784866000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b908115614fcb575b5015614f7b57505050565b6104c6906040519384937f4baa2a4d000000000000000000000000000000000000000000000000000000008552600485016040919493926001600160a01b03606083019616825260208201520152565b61501c9150837f00000000000000000000000000000000000000000000000000000000000000006000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b38614f70565b7f00000000000000000000000000000000000000000000000000000000000000026150738183856000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b8015615084575b15614f7b57505050565b506150d581837f00000000000000000000000000000000000000000000000000000000000000006000526101fe6020526001600160a01b036040600020911660005260205260406000205416151590565b61507a565b909291926150e7816144f3565b916150f560405193846144d0565b8294828452828201116126be576020614d359301906143dc565b601f8260209493601f19938186528686013760008582860101520116010190565b818102929181159184041417156149fb57565b6003111561514d57565b634e487b7160e01b600052602160045260246000fd5b51906001600160a01b03821682036126be57565b908160209103126126be575180151581036126be5790565b1561519657565b608460405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152fd5b9291906001600160a01b03841661521881151561518f565b6152368461522584614cf6565b61522e86614cf6565b90883361552a565b60009282845260209460978652604096878620848752875287862061525c848254614b8e565b905583868951878152858a8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628b3392a43b61529e575b50505050505050565b6152f99286928689518096819582947ff23a6e61000000000000000000000000000000000000000000000000000000009a8b85523360048601528560248601526044850152606484015260a0608484015260a48301906143ff565b03925af183918161546f575b506153d5575050600191615317614c69565b6308c379a01461539f575b505061533657505b38808080808080615295565b5162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d4552433131353560448201527f526563656976657220696d706c656d656e7465720000000000000000000000006064820152608490fd5b6153a7614c87565b91826153b35750615322565b846104c691505192839262461bcd60e51b8452600484015260248301906143ff565b7fffffffff00000000000000000000000000000000000000000000000000000000160391506154069050575061532a565b5162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a6563746560448201527f6420746f6b656e730000000000000000000000000000000000000000000000006064820152608490fd5b615487919250853d87116105c8576105b981836144d0565b9038615305565b90816000526101c66020526040600020906040516154ab81614484565b6154b483614da8565b81526154d88260406002600187015496602086019788520154930192808452614b8e565b92518093116154e75750505050565b608494505190604051937f1255c8fd0000000000000000000000000000000000000000000000000000000085526004850152602484015260448301526064820152fd5b9091926001600160a01b0394856101cb5416928361554b5750505050505050565b833b156126be576155cc87936000979361267e6155b98a966040519c8d9b8c9a8b997f80b10ace000000000000000000000000000000000000000000000000000000008b523060048c01521660248a01528960448a015216606488015260e0608488015260e48701906145e5565b60031993848783030160a48801526145e5565b03925af180156126b2576155e6575b808080808080615295565b6155ef906144a0565b386155db565b9490926001600160a01b0395866101cb54169384615618575b5050505050505050565b843b156126be57600096889461267e6155b98a9688615688966040519e8f9d8e9c8d9b7f80b10ace000000000000000000000000000000000000000000000000000000008d528c6004309101521660248c01521660448a015216606488015260e0608488015260e48701906145e5565b03925af180156126b2576156a3575b8080808080808061560e565b6156ac906144a0565b38615697565b6020818303126126be5780519067ffffffffffffffff82116126be57019080601f830112156126be578151614561926020016150da565b6001600160a01b0361571a7f0000000000000000000000000000000000000000000000000000000000000000615b47565b16806157295750614561615787565b6000600491604051928380927fe8a3d4850000000000000000000000000000000000000000000000000000000082525afa9081156126b25760009161576c575090565b614561913d8091833e61577f81836144d0565b8101906156b2565b60008080526101c690816020526040916157a383832054614d6e565b61585e575080805261012d6020526001600160a01b039080828482205416801561582d575b60248551809581937f0e89341c000000000000000000000000000000000000000000000000000000008352856004840152165afa9283156158235750809261580f57505090565b61456192503d8091833e61577f81836144d0565b51903d90823e3d90fd5b50507f00000000000000000000000000000000000000000000000000000000000000008152808284822054166157c8565b8180526020522061456190614da8565b6000908082526101c6806020526158886040842054614d6e565b6158f25750816001600160a01b0361589f83615b47565b16916024604051809481937f0e89341c00000000000000000000000000000000000000000000000000000000835260048301525afa9182156158e657809261580f57505090565b604051903d90823e3d90fd5b9161456192604092825260205220614da8565b6101c980546001600160a01b0392831673ffffffffffffffffffffffffffffffffffffffff19821681179092556040805193909116835260208301919091527f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a160006040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f3391806159db819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b0390a3565b6001600160a01b036101ca911673ffffffffffffffffffffffffffffffffffffffff1982541617905560016040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f3391806159db819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b7f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca60008281526101fe94856020526001600160a01b0360408320951694858352602052604082205417948382526020526040812084825260205284604082205580a4565b7f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca60008281526101fe94856020526001600160a01b03604083209516948583526020526040822054901916948382526020526040812084825260205284604082205580a4565b60005261012d6020526001600160a01b03908160406000205416918215615b6b5750565b9091507f00000000000000000000000000000000000000000000000000000000000000006000526040600020541690565b6040805191615baa83614484565b60009081845281836020958287820152015281526101609081845282812090835191615bd583614484565b549263ffffffff9283851681528385881c16878201526001600160a01b038095871c168087830152615c5057507f00000000000000000000000000000000000000000000000000000000000000008252855283902083519490615c3786614484565b5491808316865282821c1690850152821c169082015290565b9550505050505090565b8115615c64570490565b634e487b7160e01b600052601260045260246000fd5b615c8690939293615b9c565b9263ffffffff9182855116908115615cd45790615ca592910690614b8e565b9060001981855116018181116149fb576001600160a01b0392604092615ccc921690615c5a565b930151169190565b505050509060406001600160a01b039101511690600090565b63ffffffff60018184511614615dd0578160005261016060205260406000209083511681549067ffffffff00000000602086015160201b16907fffffffff000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffff0000000000000000604088015160401b16931617171790557f5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d604051806159db33958291909160406001600160a01b0381606084019563ffffffff8082511686526020820151166020860152015116910152565b60046040517f0d9b92f1000000000000000000000000000000000000000000000000000000008152fd5b9190615e0581614564565b90615e1360405192836144d0565b808252601f19615e2282614564565b0160005b818110615eec575050819360005b828110615e415750505050565b8060051b8201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1833603018112156126be5782019081359167ffffffffffffffff83116126be5760208091019083360382136126be57600080615ead615ecc94615ee797369161450f565b615eb56148f6565b9381519101305af4615ec56148c6565b9030615efd565b615ed68287614a11565b52615ee18186614a11565b506149ec565b615e34565b806060602080938701015201615e26565b919260609115615f61575050815115615f14575090565b3b15615f1d5790565b606460405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b909392614d359250614d3756fea26469706673582212200891e324b33d842d5ea9926e249cee81b1b76d106003f0c8e06b0e0b7cc5c91f64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000002c2ad68fd9000000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d0
-----Decoded View---------------
Arg [0] : _mintFeeAmount (uint256): 777000000000000
Arg [1] : _mintFeeRecipient (address): 0xd1d1D4e36117aB794ec5d4c78cBD3a8904E691D0
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000002c2ad68fd9000
Arg [1] : 000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d0
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 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.