Source Code
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
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 3000 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 "@zoralabs/openzeppelin-contracts-upgradeable/contracts/token/ERC1155/ERC1155Upgradeable.sol";
import {ReentrancyGuardUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol";
import {UUPSUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol";
import {IERC1155MetadataURIUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC1155MetadataURIUpgradeable.sol";
import {IERC165Upgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC165Upgradeable.sol";
import {IProtocolRewards} from "@zoralabs/protocol-rewards/dist/contracts/interfaces/IProtocolRewards.sol";
import {ERC1155Rewards} from "@zoralabs/protocol-rewards/dist/contracts/abstract/ERC1155/ERC1155Rewards.sol";
import {ERC1155RewardsStorageV1} from "@zoralabs/protocol-rewards/dist/contracts/abstract/ERC1155/ERC1155RewardsStorageV1.sol";
import {IZoraCreator1155} from "../interfaces/IZoraCreator1155.sol";
import {IZoraCreator1155Initializer} from "../interfaces/IZoraCreator1155Initializer.sol";
import {ReentrancyGuardUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol";
import {UUPSUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol";
import {MathUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/utils/math/MathUpgradeable.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 {IFactoryManagedUpgradeGate} from "../interfaces/IFactoryManagedUpgradeGate.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,
IZoraCreator1155Initializer,
ContractVersionBase,
ReentrancyGuardUpgradeable,
PublicMulticall,
ERC1155Upgradeable,
MintFeeManager,
UUPSUpgradeable,
CreatorRendererControl,
LegacyNamingControl,
ZoraCreator1155StorageV1,
CreatorPermissionControl,
CreatorRoyaltiesControl,
ERC1155Rewards,
ERC1155RewardsStorageV1
{
/// @notice This user role allows for any action to be performed
uint256 public constant PERMISSION_BIT_ADMIN = 2 ** 1;
/// @notice This user role allows for only mint actions to be performed
uint256 public constant PERMISSION_BIT_MINTER = 2 ** 2;
/// @notice This user role allows for only managing sales configurations
uint256 public constant PERMISSION_BIT_SALES = 2 ** 3;
/// @notice This user role allows for only managing metadata configuration
uint256 public constant PERMISSION_BIT_METADATA = 2 ** 4;
/// @notice This user role allows for only withdrawing funds and setting funds withdraw address
uint256 public constant PERMISSION_BIT_FUNDS_MANAGER = 2 ** 5;
/// @notice Factory contract
IFactoryManagedUpgradeGate internal immutable factory;
constructor(
uint256 _mintFeeAmount,
address _mintFeeRecipient,
address _factory,
address _protocolRewards
) MintFeeManager(_mintFeeAmount, _mintFeeRecipient) ERC1155Rewards(_protocolRewards, _mintFeeRecipient) initializer {
factory = IFactoryManagedUpgradeGate(_factory);
}
/// @notice Initializes the contract
/// @param contractName the legacy on-chain contract name
/// @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 contractName,
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);
_setName(contractName);
// 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 | role))) {
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 storage 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
/// @param maxSupply The maximum supply of the token
function setupNewToken(
string calldata newURI,
uint256 maxSupply
) public onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_MINTER) nonReentrant returns (uint256) {
uint256 tokenId = _setupNewTokenAndPermission(newURI, maxSupply, msg.sender, PERMISSION_BIT_ADMIN);
return tokenId;
}
/// @notice Set up a new token with a create referral
/// @param newURI The URI for the token
/// @param maxSupply The maximum supply of the token
/// @param createReferral The address of the create referral
function setupNewTokenWithCreateReferral(
string calldata newURI,
uint256 maxSupply,
address createReferral
) public onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_MINTER) nonReentrant returns (uint256) {
uint256 tokenId = _setupNewTokenAndPermission(newURI, maxSupply, msg.sender, PERMISSION_BIT_ADMIN);
_setCreateReferral(tokenId, createReferral);
return tokenId;
}
function _setupNewTokenAndPermission(string calldata newURI, uint256 maxSupply, address user, uint256 permission) internal returns (uint256) {
uint256 tokenId = _setupNewToken(newURI, maxSupply);
_addPermission(tokenId, user, permission);
if (bytes(newURI).length > 0) {
emit URI(newURI, tokenId);
}
emit SetupNewToken(tokenId, user, 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();
}
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(msg.sender, tokenId, quantity, ethValueSent, minterArguments).commands, ethValueSent, tokenId);
emit Purchased(msg.sender, address(minter), tokenId, quantity, msg.value);
}
/// @notice Get the creator reward recipient address
/// @dev The creator is not enforced to set a funds recipient address, so in that case the reward would be claimable by creator's contract
function getCreatorRewardRecipient() public view returns (address payable) {
return config.fundsRecipient != address(0) ? config.fundsRecipient : payable(address(this));
}
/// @notice Mint tokens and payout rewards given a minter contract, minter arguments, a finder, and a origin
/// @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
/// @param mintReferral The referrer of the mint
function mintWithRewards(
IMinter1155 minter,
uint256 tokenId,
uint256 quantity,
bytes calldata minterArguments,
address mintReferral
) external payable nonReentrant {
// Require admin from the minter to mint
_requireAdminOrRole(address(minter), tokenId, PERMISSION_BIT_MINTER);
// Get value sent and handle mint rewards
uint256 ethValueSent = _handleRewardsAndGetValueSent(msg.value, quantity, getCreatorRewardRecipient(), createReferrals[tokenId], mintReferral);
// Execute commands returned from minter
_executeCommands(minter.requestMint(msg.sender, 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
function setTokenMetadataRenderer(uint256 tokenId, IRenderer1155 renderer) external nonReentrant onlyAdminOrRole(tokenId, PERMISSION_BIT_METADATA) {
_setRenderer(tokenId, renderer);
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, TransferHelperUtils.FUNDS_SEND_NORMAL_GAS_LIMIT)) {
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();
}
_mint(recipient, tokenId, quantity, "");
} else {
// no-op
}
}
}
/// @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, bytes memory why) = address(salesConfig).call(data);
if (!success) {
revert CallFailed(why);
}
}
/// @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 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 || ERC1155Upgradeable.supportsInterface(interfaceId);
}
function _handleSupplyRoyalty(uint256 tokenId, uint256 mintAmount, bytes memory data) internal returns (uint256 totalRoyaltyMints) {
uint256 royaltyMintSchedule = royalties[tokenId].royaltyMintSchedule;
if (royaltyMintSchedule == 0) {
royaltyMintSchedule = royalties[CONTRACT_BASE_ID].royaltyMintSchedule;
}
if (royaltyMintSchedule == 0) {
// If we still have no schedule, return 0 supply royalty.
return 0;
}
uint256 maxSupply = tokens[tokenId].maxSupply;
uint256 totalMinted = tokens[tokenId].totalMinted;
totalRoyaltyMints = (mintAmount + (totalMinted % royaltyMintSchedule)) / (royaltyMintSchedule - 1);
totalRoyaltyMints = MathUpgradeable.min(totalRoyaltyMints, maxSupply - (mintAmount + totalMinted));
if (totalRoyaltyMints > 0) {
address royaltyRecipient = royalties[tokenId].royaltyRecipient;
if (royaltyRecipient == address(0)) {
royaltyRecipient = royalties[CONTRACT_BASE_ID].royaltyRecipient;
}
// If we have no recipient set, return 0 supply royalty.
if (royaltyRecipient == address(0)) {
return 0;
}
super._mint(royaltyRecipient, tokenId, totalRoyaltyMints, data);
}
}
/// 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 {
uint256 supplyRoyaltyMints = _handleSupplyRoyalty(id, amount, data);
_requireCanMintQuantity(id, amount + supplyRoyaltyMints);
super._mint(to, id, amount, data);
tokens[id].totalMinted += amount + supplyRoyaltyMints;
}
/// @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) {
uint256 supplyRoyaltyMints = _handleSupplyRoyalty(ids[i], amounts[i], data);
_requireCanMintQuantity(ids[i], amounts[i] + supplyRoyaltyMints);
tokens[ids[i]].totalMinted += amounts[i] + supplyRoyaltyMints;
}
}
/// @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 _beforeBatchTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal override {
super._beforeBatchTokenTransfer(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 Set funds recipient address
/// @param fundsRecipient new funds recipient address
function setFundsRecipient(address payable fundsRecipient) external onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_FUNDS_MANAGER) {
_setFundsRecipient(fundsRecipient);
}
/// @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 Allows the create referral to update the address that can claim their rewards
function updateCreateReferral(uint256 tokenId, address recipient) external {
if (msg.sender != createReferrals[tokenId]) revert ONLY_CREATE_REFERRAL();
_setCreateReferral(tokenId, recipient);
}
function _setCreateReferral(uint256 tokenId, address recipient) internal {
createReferrals[tokenId] = recipient;
}
/// @notice Withdraws all ETH from the contract to the funds recipient address
function withdraw() public onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_FUNDS_MANAGER) {
uint256 contractValue = address(this).balance;
if (!TransferHelperUtils.safeSendETH(config.fundsRecipient, contractValue, TransferHelperUtils.FUNDS_SEND_NORMAL_GAS_LIMIT)) {
revert ETHWithdrawFailed(config.fundsRecipient, contractValue);
}
}
/// @notice Withdraws ETH from the Zora Rewards contract
function withdrawRewards(address to, uint256 amount) public onlyAdminOrRole(CONTRACT_BASE_ID, PERMISSION_BIT_FUNDS_MANAGER) {
bytes memory data = abi.encodeWithSelector(IProtocolRewards.withdraw.selector, to, amount);
(bool success, ) = address(protocolRewards).call(data);
if (!success) {
revert ProtocolRewardsWithdrawFailed(msg.sender, to, amount);
}
}
/// ///
/// 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 view override onlyAdmin(CONTRACT_BASE_ID) {
if (!factory.isRegisteredUpgradePath(_getImplementation(), _newImpl)) {
revert();
}
}
}// SPDX-License-Identifier: MIT
// Modifications from OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/ERC1155.sol):
// - Revert strings replaced with custom errors
// - Decoupled hooks
// - `_beforeTokenTransfer` --> `_beforeTokenTransfer` & `_beforeBatchTokenTransfer`
// - `_afterTokenTransfer` --> `_afterTokenTransfer` & `_afterBatchTokenTransfer`
// - Minor gas optimizations (eg. array length caching, unchecked loop iteration)
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";
error ERC1155_ADDRESS_ZERO_IS_NOT_A_VALID_OWNER();
error ERC1155_ACCOUNTS_AND_IDS_LENGTH_MISMATCH();
error ERC1155_IDS_AND_AMOUNTS_LENGTH_MISMATCH();
error ERC1155_CALLER_IS_NOT_TOKEN_OWNER_OR_APPROVED();
error ERC1155_TRANSFER_TO_ZERO_ADDRESS();
error ERC1155_INSUFFICIENT_BALANCE_FOR_TRANSFER();
error ERC1155_MINT_TO_ZERO_ADDRESS();
error ERC1155_BURN_FROM_ZERO_ADDRESS();
error ERC1155_BURN_AMOUNT_EXCEEDS_BALANCE();
error ERC1155_SETTING_APPROVAL_FOR_SELF();
error ERC1155_ERC1155RECEIVER_REJECTED_TOKENS();
error ERC1155_TRANSFER_TO_NON_ERC1155RECEIVER_IMPLEMENTER();
/**
* @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) {
if (account == address(0)) {
revert 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 batchBalances) {
uint256 numAccounts = accounts.length;
if (numAccounts != ids.length) {
revert ERC1155_ACCOUNTS_AND_IDS_LENGTH_MISMATCH();
}
batchBalances = new uint256[](numAccounts);
unchecked {
for (uint256 i; i < numAccounts; ++i) {
batchBalances[i] = balanceOf(accounts[i], ids[i]);
}
}
}
/**
* @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 {
if (from != _msgSender() && !isApprovedForAll(from, _msgSender())) {
revert 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 {
if (from != _msgSender() && !isApprovedForAll(from, _msgSender())) {
revert 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 {
if (to == address(0)) {
revert ERC1155_TRANSFER_TO_ZERO_ADDRESS();
}
address operator = _msgSender();
_beforeTokenTransfer(operator, from, to, id, amount, data);
uint256 fromBalance = _balances[id][from];
if (fromBalance < amount) {
revert 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, id, amount, 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 {
uint256 numIds = ids.length;
if (numIds != amounts.length) {
revert ERC1155_ACCOUNTS_AND_IDS_LENGTH_MISMATCH();
}
if (to == address(0)) {
revert ERC1155_TRANSFER_TO_ZERO_ADDRESS();
}
address operator = _msgSender();
_beforeBatchTokenTransfer(operator, from, to, ids, amounts, data);
uint256 id;
uint256 amount;
uint256 fromBalance;
for (uint256 i; i < numIds; ) {
id = ids[i];
amount = amounts[i];
fromBalance = _balances[id][from];
if (fromBalance < amount) {
revert ERC1155_INSUFFICIENT_BALANCE_FOR_TRANSFER();
}
_balances[id][to] += amount;
unchecked {
_balances[id][from] = fromBalance - amount;
++i;
}
}
emit TransferBatch(operator, from, to, ids, amounts);
_afterBatchTokenTransfer(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 {
if (to == address(0)) {
revert ERC1155_MINT_TO_ZERO_ADDRESS();
}
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), to, id, amount, data);
_balances[id][to] += amount;
emit TransferSingle(operator, address(0), to, id, amount);
_afterTokenTransfer(operator, address(0), to, id, amount, 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 {
if (to == address(0)) {
revert ERC1155_MINT_TO_ZERO_ADDRESS();
}
uint256 numIds = ids.length;
if (numIds != amounts.length) {
revert ERC1155_IDS_AND_AMOUNTS_LENGTH_MISMATCH();
}
address operator = _msgSender();
_beforeBatchTokenTransfer(operator, address(0), to, ids, amounts, data);
for (uint256 i; i < numIds; ) {
_balances[ids[i]][to] += amounts[i];
unchecked {
++i;
}
}
emit TransferBatch(operator, address(0), to, ids, amounts);
_afterBatchTokenTransfer(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 {
if (from == address(0)) {
revert ERC1155_BURN_FROM_ZERO_ADDRESS();
}
address operator = _msgSender();
_beforeTokenTransfer(operator, from, address(0), id, amount, "");
uint256 fromBalance = _balances[id][from];
if (fromBalance < amount) {
revert ERC1155_BURN_AMOUNT_EXCEEDS_BALANCE();
}
unchecked {
_balances[id][from] = fromBalance - amount;
}
emit TransferSingle(operator, from, address(0), id, amount);
_afterTokenTransfer(operator, from, address(0), id, amount, "");
}
/**
* @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 {
if (from == address(0)) {
revert ERC1155_BURN_FROM_ZERO_ADDRESS();
}
uint256 numIds = ids.length;
if (numIds != amounts.length) {
revert ERC1155_IDS_AND_AMOUNTS_LENGTH_MISMATCH();
}
address operator = _msgSender();
_beforeBatchTokenTransfer(operator, from, address(0), ids, amounts, "");
uint256 id;
uint256 amount;
uint256 fromBalance;
for (uint256 i; i < numIds; ) {
id = ids[i];
amount = amounts[i];
fromBalance = _balances[id][from];
if (fromBalance < amount) {
revert ERC1155_BURN_AMOUNT_EXCEEDS_BALANCE();
}
unchecked {
_balances[id][from] = fromBalance - amount;
++i;
}
}
emit TransferBatch(operator, from, address(0), ids, amounts);
_afterBatchTokenTransfer(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 {
if (owner == operator) {
revert ERC1155_SETTING_APPROVAL_FOR_SELF();
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Hook that is called before a single token transfer.
*/
function _beforeTokenTransfer(
address operator,
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual { }
/**
* @dev Hook that is called before a batch token transfer.
*/
function _beforeBatchTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {}
/**
* @dev Hook that is called after a single token transfer.
*/
function _afterTokenTransfer(
address operator,
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {}
/**
* @dev Hook that is called after a batch token transfer.
*/
function _afterBatchTokenTransfer(
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();
}
}
}
/**
* @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.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 Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _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) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
import "./Initializable.sol";
error FUNCTION_MUST_BE_CALLED_THROUGH_DELEGATECALL();
error FUNCTION_MUST_BE_CALLED_THROUGH_ACTIVE_PROXY();
error UUPS_UPGRADEABLE_MUST_NOT_BE_CALLED_THROUGH_DELEGATECALL();
/**
* @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() {
if (address(this) == __self) {
revert FUNCTION_MUST_BE_CALLED_THROUGH_DELEGATECALL();
}
if (_getImplementation() != __self) {
revert 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() {
if (address(this) != __self) {
revert UUPS_UPGRADEABLE_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.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public 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.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public 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 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
pragma solidity 0.8.17;
/// @title IProtocolRewards
/// @notice The interface for deposits & withdrawals of protocol rewards
interface IProtocolRewards {
event RewardsDeposit(
address indexed creator,
address indexed createReferral,
address indexed mintReferral,
address firstMinter,
address zora,
address from,
uint256 creatorReward,
uint256 createReferralReward,
uint256 mintReferralReward,
uint256 firstMinterReward,
uint256 zoraReward
);
event Deposit(address indexed from, address indexed to, uint256 amount, string comment);
event Withdraw(address indexed from, address indexed to, uint256 amount);
error ADDRESS_ZERO();
error ARRAY_LENGTH_MISMATCH();
error INVALID_DEPOSIT();
error INVALID_SIGNATURE();
error INVALID_WITHDRAW();
error SIGNATURE_DEADLINE_EXPIRED();
error TRANSFER_FAILED();
function deposit(address to, string calldata comment) external payable;
function depositBatch(address[] calldata recipients, uint256[] calldata amounts, string calldata comment) external payable;
function depositRewards(
address creator,
uint256 creatorReward,
address createReferral,
uint256 createReferralReward,
address mintReferral,
uint256 mintReferralReward,
address firstMinter,
uint256 firstMinterReward,
address zora,
uint256 zoraReward
) external payable;
function withdraw(address to, uint256 amount) external;
function withdrawWithSig(address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {RewardSplits} from "../RewardSplits.sol";
/// @notice The base logic for handling Zora ERC-1155 protocol rewards
/// @dev Used in https://github.com/ourzora/zora-1155-contracts/blob/main/src/nft/ZoraCreator1155Impl.sol
abstract contract ERC1155Rewards is RewardSplits {
constructor(address _protocolRewards, address _zoraRewardRecipient) payable RewardSplits(_protocolRewards, _zoraRewardRecipient) {}
function _handleRewardsAndGetValueSent(
uint256 msgValue,
uint256 numTokens,
address creator,
address createReferral,
address mintReferral
) internal returns (uint256) {
uint256 totalReward = computeTotalReward(numTokens);
if (msgValue < totalReward) {
revert INVALID_ETH_AMOUNT();
} else if (msgValue == totalReward) {
_depositFreeMintRewards(totalReward, numTokens, creator, createReferral, mintReferral);
return 0;
} else {
_depositPaidMintRewards(totalReward, numTokens, creator, createReferral, mintReferral);
unchecked {
return msgValue - totalReward;
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
contract ERC1155RewardsStorageV1 {
mapping(uint256 => address) public createReferrals;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {IERC165Upgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC165Upgradeable.sol";
import {IERC1155MetadataURIUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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 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 CallFailed(bytes reason);
error Renderer_NotValidRendererContract();
error ETHWithdrawFailed(address recipient, uint256 amount);
error FundsWithdrawInsolvent(uint256 amount, uint256 contractValue);
error ProtocolRewardsWithdrawFailed(address caller, address recipient, uint256 amount);
error CannotMintMoreTokens(uint256 tokenId, uint256 quantity, uint256 totalMinted, uint256 maxSupply);
/// @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;
// Public interface for `setTokenMetadataRenderer(uint256, address) has been deprecated.
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 {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol";
interface IZoraCreator1155Initializer {
function initialize(
string memory contractName,
string memory newContractURI,
ICreatorRoyaltiesControl.RoyaltyConfiguration memory defaultRoyaltyConfiguration,
address payable defaultAdmin,
bytes[] calldata setupActions
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library MathUpgradeable {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// 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.4.0";
}
}// 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;
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) internal {
customRenderers[tokenId] = renderer;
if (address(renderer) != address(0)) {
if (!renderer.supportsInterface(type(IRenderer1155).interfaceId)) {
revert RendererNotValid(address(renderer));
}
}
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 {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) {
if (royalties[tokenId].royaltyRecipient != address(0)) {
return royalties[tokenId];
}
// 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();
}
// Don't allow setting royalties to burn address
if (configuration.royaltyRecipient == address(0) && (configuration.royaltyMintSchedule > 0 || configuration.royaltyBPS > 0)) {
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;
/// @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;
import {IERC165Upgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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;
import {IERC165Upgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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 "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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;
/// @notice Factory Upgrade Gate Admin Factory Implementation – Allows specific contract upgrades as a safety measure
interface IFactoryManagedUpgradeGate {
/// @notice If an implementation is registered by the Builder DAO as an optional upgrade
/// @param baseImpl The base implementation address
/// @param upgradeImpl The upgrade implementation address
function isRegisteredUpgradePath(address baseImpl, address upgradeImpl) external view returns (bool);
/// @notice Called by the Builder DAO to offer implementation upgrades for created DAOs
/// @param baseImpls The base implementation addresses
/// @param upgradeImpl The upgrade implementation address
function registerUpgradePath(address[] memory baseImpls, address upgradeImpl) external;
/// @notice Called by the Builder DAO to remove an upgrade
/// @param baseImpl The base implementation address
/// @param upgradeImpl The upgrade implementation address
function removeUpgradePath(address baseImpl, address upgradeImpl) external;
event UpgradeRegistered(address indexed baseImpl, address indexed upgradeImpl);
event UpgradeRemoved(address indexed baseImpl, address indexed upgradeImpl);
}// 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;
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.safeSendETH(mintFeeRecipient, totalFee, TransferHelperUtils.FUNDS_SEND_LOW_GAS_LIMIT)) {
revert CannotSendMintFee(mintFeeRecipient, totalFee);
}
}
}
}// 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;
contract SharedBaseConstants {
uint256 public constant CONTRACT_BASE_ID = 0;
}// 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_NORMAL_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 safeSendETH(address recipient, uint256 value, uint256 gasLimit) internal returns (bool success) {
(success, ) = recipient.call{value: value, gas: gasLimit}("");
}
}// 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 public 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
// 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 (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 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;
error ADDRESS_INSUFFICIENT_BALANCE();
error ADDRESS_UNABLE_TO_SEND_VALUE();
error ADDRESS_LOW_LEVEL_CALL_FAILED();
error ADDRESS_LOW_LEVEL_CALL_WITH_VALUE_FAILED();
error ADDRESS_INSUFFICIENT_BALANCE_FOR_CALL();
error ADDRESS_LOW_LEVEL_STATIC_CALL_FAILED();
error ADDRESS_CALL_TO_NON_CONTRACT();
/**
* @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
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [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://consensys.net/diligence/blog/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 {
if (address(this).balance > amount) {
revert ADDRESS_INSUFFICIENT_BALANCE();
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert ADDRESS_UNABLE_TO_SEND_VALUE();
}
}
/**
* @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);
}
/**
* @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) {
if (address(this).balance < value) {
revert ADDRESS_INSUFFICIENT_BALANCE();
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @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
) 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
if (!isContract(target)) {
revert ADDRESS_CALL_TO_NON_CONTRACT();
}
}
return returndata;
} else {
_revert(returndata);
}
}
/**
* @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
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata);
}
}
function _revert(bytes memory returndata) 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 ADDRESS_LOW_LEVEL_CALL_FAILED();
}
}
}// 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 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 (last updated v4.8.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
error INITIALIZABLE_CONTRACT_ALREADY_INITIALIZED();
error INITIALIZABLE_CONTRACT_IS_NOT_INITIALIZING();
error INITIALIZABLE_CONTRACT_IS_INITIALIZING();
/**
* @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]
* ```solidity
* 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;
if ((!isTopLevelCall || _initialized != 0) && (AddressUpgradeable.isContract(address(this)) || _initialized != 1)) {
revert INITIALIZABLE_CONTRACT_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) {
if (_initializing || _initialized >= version) {
revert INITIALIZABLE_CONTRACT_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() {
if (!_initializing) {
revert 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 {
if (_initializing) {
revert INITIALIZABLE_CONTRACT_IS_INITIALIZING();
}
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// 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";
error ERC1967_NEW_IMPL_NOT_CONTRACT();
error ERC1967_UNSUPPORTED_PROXIABLEUUID();
error ERC1967_NEW_IMPL_NOT_UUPS();
error ERC1967_NEW_ADMIN_IS_ZERO_ADDRESS();
error ERC1967_NEW_BEACON_IS_NOT_CONTRACT();
error ERC1967_BEACON_IMPL_IS_NOT_CONTRACT();
error ADDRESS_DELEGATECALL_TO_NON_CONTRACT();
/**
* @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._
*/
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 {
if (!AddressUpgradeable.isContract(newImplementation)) {
revert ERC1967_NEW_IMPL_NOT_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) {
if (slot != _IMPLEMENTATION_SLOT) {
revert ERC1967_UNSUPPORTED_PROXIABLEUUID();
}
} catch {
revert ERC1967_NEW_IMPL_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 {
if (newAdmin == address(0)) {
revert ERC1967_NEW_ADMIN_IS_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 {
if (!AddressUpgradeable.isContract(newBeacon)) {
revert ERC1967_NEW_BEACON_IS_NOT_CONTRACT();
}
if (!AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation())) {
revert ERC1967_BEACON_IMPL_IS_NOT_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) {
if (!AddressUpgradeable.isContract(target)) {
revert ADDRESS_DELEGATECALL_TO_NON_CONTRACT();
}
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return AddressUpgradeable.verifyCallResult(success, returndata);
}
/**
* @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 {IProtocolRewards} from "../interfaces/IProtocolRewards.sol";
struct RewardsSettings {
uint256 creatorReward;
uint256 createReferralReward;
uint256 mintReferralReward;
uint256 firstMinterReward;
uint256 zoraReward;
}
/// @notice Common logic for between Zora ERC-721 & ERC-1155 contracts for protocol reward splits & deposits
abstract contract RewardSplits {
error CREATOR_FUNDS_RECIPIENT_NOT_SET();
error INVALID_ADDRESS_ZERO();
error INVALID_ETH_AMOUNT();
error ONLY_CREATE_REFERRAL();
uint256 internal constant TOTAL_REWARD_PER_MINT = 0.000777 ether;
uint256 internal constant CREATOR_REWARD = 0.000333 ether;
uint256 internal constant FIRST_MINTER_REWARD = 0.000111 ether;
uint256 internal constant CREATE_REFERRAL_FREE_MINT_REWARD = 0.000111 ether;
uint256 internal constant MINT_REFERRAL_FREE_MINT_REWARD = 0.000111 ether;
uint256 internal constant ZORA_FREE_MINT_REWARD = 0.000111 ether;
uint256 internal constant MINT_REFERRAL_PAID_MINT_REWARD = 0.000222 ether;
uint256 internal constant CREATE_REFERRAL_PAID_MINT_REWARD = 0.000222 ether;
uint256 internal constant ZORA_PAID_MINT_REWARD = 0.000222 ether;
address internal immutable zoraRewardRecipient;
IProtocolRewards internal immutable protocolRewards;
constructor(address _protocolRewards, address _zoraRewardRecipient) payable {
if (_protocolRewards == address(0) || _zoraRewardRecipient == address(0)) {
revert INVALID_ADDRESS_ZERO();
}
protocolRewards = IProtocolRewards(_protocolRewards);
zoraRewardRecipient = _zoraRewardRecipient;
}
function computeTotalReward(uint256 numTokens) public pure returns (uint256) {
return numTokens * TOTAL_REWARD_PER_MINT;
}
function computeFreeMintRewards(uint256 numTokens) public pure returns (RewardsSettings memory) {
return
RewardsSettings({
creatorReward: numTokens * CREATOR_REWARD,
createReferralReward: numTokens * CREATE_REFERRAL_FREE_MINT_REWARD,
mintReferralReward: numTokens * MINT_REFERRAL_FREE_MINT_REWARD,
firstMinterReward: numTokens * FIRST_MINTER_REWARD,
zoraReward: numTokens * ZORA_FREE_MINT_REWARD
});
}
function computePaidMintRewards(uint256 numTokens) public pure returns (RewardsSettings memory) {
return
RewardsSettings({
creatorReward: 0,
createReferralReward: numTokens * CREATE_REFERRAL_PAID_MINT_REWARD,
mintReferralReward: numTokens * MINT_REFERRAL_PAID_MINT_REWARD,
firstMinterReward: numTokens * FIRST_MINTER_REWARD,
zoraReward: numTokens * ZORA_PAID_MINT_REWARD
});
}
function _depositFreeMintRewards(uint256 totalReward, uint256 numTokens, address creator, address createReferral, address mintReferral) internal {
RewardsSettings memory settings = computeFreeMintRewards(numTokens);
if (createReferral == address(0)) {
createReferral = zoraRewardRecipient;
}
if (mintReferral == address(0)) {
mintReferral = zoraRewardRecipient;
}
protocolRewards.depositRewards{value: totalReward}(
creator,
settings.creatorReward,
createReferral,
settings.createReferralReward,
mintReferral,
settings.mintReferralReward,
creator,
settings.firstMinterReward,
zoraRewardRecipient,
settings.zoraReward
);
}
function _depositPaidMintRewards(uint256 totalReward, uint256 numTokens, address creator, address createReferral, address mintReferral) internal {
RewardsSettings memory settings = computePaidMintRewards(numTokens);
if (createReferral == address(0)) {
createReferral = zoraRewardRecipient;
}
if (mintReferral == address(0)) {
mintReferral = zoraRewardRecipient;
}
protocolRewards.depositRewards{value: totalReward}(
address(0),
0,
createReferral,
settings.createReferralReward,
mintReferral,
settings.mintReferralReward,
creator,
settings.firstMinterReward,
zoraRewardRecipient,
settings.zoraReward
);
}
}// 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;
interface IOwnable {
function owner() external returns (address);
event OwnershipTransferred(address lastOwner, address newOwner);
}// 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 {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;
/// 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;
/// @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 {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 {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
// OpenZeppelin Contracts (last updated v4.9.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
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;
contract LegacyNamingStorageV1 {
string internal _name;
uint256[50] private __gap;
}// 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
// OpenZeppelin Contracts (last updated v4.9.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
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [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://consensys.net/diligence/blog/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.8.0/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 (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.7.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
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:
* ```solidity
* 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`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlotUpgradeable {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes 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
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// 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
// 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);
}{
"remappings": [
"@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
"@zoralabs/openzeppelin-contracts-upgradeable/=node_modules/@zoralabs/openzeppelin-contracts-upgradeable/",
"@zoralabs/protocol-rewards/=node_modules/@zoralabs/protocol-rewards/",
"_imagine/=_imagine/",
"ds-test/=node_modules/ds-test/src/",
"forge-std/=node_modules/forge-std/src/",
"mint/=_imagine/mint/"
],
"optimizer": {
"enabled": true,
"runs": 3000
},
"metadata": {
"useLiteralContent": false,
"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
Contract ABI
API[{"inputs":[{"internalType":"uint256","name":"_mintFeeAmount","type":"uint256"},{"internalType":"address","name":"_mintFeeRecipient","type":"address"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_protocolRewards","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ADDRESS_DELEGATECALL_TO_NON_CONTRACT","type":"error"},{"inputs":[],"name":"ADDRESS_LOW_LEVEL_CALL_FAILED","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"user","type":"address"}],"name":"Burn_NotOwnerOrApproved","type":"error"},{"inputs":[],"name":"CREATOR_FUNDS_RECIPIENT_NOT_SET","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"CallFailed","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":[],"name":"ERC1155_ACCOUNTS_AND_IDS_LENGTH_MISMATCH","type":"error"},{"inputs":[],"name":"ERC1155_ADDRESS_ZERO_IS_NOT_A_VALID_OWNER","type":"error"},{"inputs":[],"name":"ERC1155_BURN_AMOUNT_EXCEEDS_BALANCE","type":"error"},{"inputs":[],"name":"ERC1155_BURN_FROM_ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"ERC1155_CALLER_IS_NOT_TOKEN_OWNER_OR_APPROVED","type":"error"},{"inputs":[],"name":"ERC1155_ERC1155RECEIVER_REJECTED_TOKENS","type":"error"},{"inputs":[],"name":"ERC1155_IDS_AND_AMOUNTS_LENGTH_MISMATCH","type":"error"},{"inputs":[],"name":"ERC1155_INSUFFICIENT_BALANCE_FOR_TRANSFER","type":"error"},{"inputs":[],"name":"ERC1155_MINT_TO_ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"ERC1155_SETTING_APPROVAL_FOR_SELF","type":"error"},{"inputs":[],"name":"ERC1155_TRANSFER_TO_NON_ERC1155RECEIVER_IMPLEMENTER","type":"error"},{"inputs":[],"name":"ERC1155_TRANSFER_TO_ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"ERC1967_NEW_IMPL_NOT_CONTRACT","type":"error"},{"inputs":[],"name":"ERC1967_NEW_IMPL_NOT_UUPS","type":"error"},{"inputs":[],"name":"ERC1967_UNSUPPORTED_PROXIABLEUUID","type":"error"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ETHWithdrawFailed","type":"error"},{"inputs":[],"name":"FUNCTION_MUST_BE_CALLED_THROUGH_ACTIVE_PROXY","type":"error"},{"inputs":[],"name":"FUNCTION_MUST_BE_CALLED_THROUGH_DELEGATECALL","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"contractValue","type":"uint256"}],"name":"FundsWithdrawInsolvent","type":"error"},{"inputs":[],"name":"INITIALIZABLE_CONTRACT_ALREADY_INITIALIZED","type":"error"},{"inputs":[],"name":"INITIALIZABLE_CONTRACT_IS_NOT_INITIALIZING","type":"error"},{"inputs":[],"name":"INVALID_ADDRESS_ZERO","type":"error"},{"inputs":[],"name":"INVALID_ETH_AMOUNT","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":"ONLY_CREATE_REFERRAL","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ProtocolRewardsWithdrawFailed","type":"error"},{"inputs":[{"internalType":"address","name":"renderer","type":"address"}],"name":"RendererNotValid","type":"error"},{"inputs":[],"name":"Renderer_NotValidRendererContract","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":[],"name":"UUPS_UPGRADEABLE_MUST_NOT_BE_CALLED_THROUGH_DELEGATECALL","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":"batchBalances","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":[{"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"computeFreeMintRewards","outputs":[{"components":[{"internalType":"uint256","name":"creatorReward","type":"uint256"},{"internalType":"uint256","name":"createReferralReward","type":"uint256"},{"internalType":"uint256","name":"mintReferralReward","type":"uint256"},{"internalType":"uint256","name":"firstMinterReward","type":"uint256"},{"internalType":"uint256","name":"zoraReward","type":"uint256"}],"internalType":"struct RewardsSettings","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"computePaidMintRewards","outputs":[{"components":[{"internalType":"uint256","name":"creatorReward","type":"uint256"},{"internalType":"uint256","name":"createReferralReward","type":"uint256"},{"internalType":"uint256","name":"mintReferralReward","type":"uint256"},{"internalType":"uint256","name":"firstMinterReward","type":"uint256"},{"internalType":"uint256","name":"zoraReward","type":"uint256"}],"internalType":"struct RewardsSettings","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"computeTotalReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"config","outputs":[{"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"}],"stateMutability":"view","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":"createReferrals","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"customRenderers","outputs":[{"internalType":"contract IRenderer1155","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCreatorRewardRecipient","outputs":[{"internalType":"address payable","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":"contractName","type":"string"},{"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":"contract IMinter1155","name":"minter","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes","name":"minterArguments","type":"bytes"},{"internalType":"address","name":"mintReferral","type":"address"}],"name":"mintWithRewards","outputs":[],"stateMutability":"payable","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"}],"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":"string","name":"newURI","type":"string"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"address","name":"createReferral","type":"address"}],"name":"setupNewTokenWithCreateReferral","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"},{"internalType":"address","name":"recipient","type":"address"}],"name":"updateCreateReferral","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"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawRewards","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
610160346200028657601f620062b038819003918201601f191683019291906001600160401b038411838510176200028b57816080928492604096875283398101031262000286578051906200005860208201620002a1565b926200007460606200006c838501620002a1565b9301620002a1565b67016345785d8a00008410156200026e576001600160a01b038581161594909190858062000264575b620002535760a08790526080523060c05261271060e05281169384159081156200024a575b5062000239576101209384526101009485526000549060ff8260081c161591828015906200022c575b8062000212575b620002015760ff19811660011760005582620001ee575b5061014093168352620001b3575b5191615ff99384620002b785396080518481816123aa0152613be0015260a0518481816122960152612339015260c051848181612b9401528181612c4e015261326e015260e0518461384e01525183818161508a015281816150e8015281816151100152818161520d01528181615272015261529a015251828181610c5401528181614fdf0152615169015251818181612cf5015261331f0152f35b61ff0019600054166000557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024986020825160018152a162000117565b61ffff1916610101176000553862000109565b8351633d5c224160e11b8152600490fd5b50303b151580620000f25750600160ff82161415620000f2565b5060ff81161515620000eb565b8151632d87658960e01b8152600490fd5b905038620000c2565b835163c64a448960e01b8152600490fd5b508015156200009d565b8151637f19df9f60e11b815260048101859052602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620002865756fe6080604052600436101561001257600080fd5b60003560e01c8062fdd58e14613e595780630114420114613e3d57806301ffc9a714613d2057806306fdde0314613c4c5780630e89341c14613c2d57806310a7eb5d14613c0357806313966db514613bc857806313af403514613b3357806317bd48bb14613a9c57806318711c7d14613a8057806318e97fd1146138ef57806323bd03861461389c5780632a55205a1461380d5780632eb2c2d6146134a2578063300ecdb91461309b5780633659cfe6146132485780633ccfd60b146131325780634132239b146130e55780634913162d1461309b5780634e1273f414612f355780634f1ef28614612c0e57806352d1902d14612b795780635c04608414612b5a5780635d0f6cba146129d157806364ea3835146129b65780636661a9ba14612815578063674cbae61461278557806369a5b3021461274f5780636b20c45414612494578063722933f71461243a578063731133e9146122d957806375794a3c146122ba578063765b0c361461227657806379502c551461221a5780637dafae4d146121e45780637f2dc61c146120965780637f77f574146120465780638621ea4b146120075780638a08eb4c14611a0b5780638c7a63ae146119945780638da5cb5b1461196c5780638ec998a0146118e7578063929a7128146118cc57806395d89b411461186e5780639c5c63c9146117c25780639dbb844d1461167a578063a0a8e46014611609578063a22cb46514611552578063a453eaf014611536578063ac9650d81461147e578063afed7e9e14611250578063bb3bafd6146111f9578063c0464356146111dd578063c238d1ee14611181578063d1ad846b14610d23578063d258609a14610cc3578063d6ef7af014610bca578063d904b94a146109e8578063dd15e05f146109b2578063e72878b414610956578063e74d86c214610927578063e8a3d485146108f3578063e985e9c51461089c578063ef71c82e14610618578063f1b0d6bb146105fc5763f242432a146102f157600080fd5b346105f75760a06003193601126105f75761030a613e88565b610312613e9e565b9060643560443560843567ffffffffffffffff81116105f757610339903690600401613ff6565b6001600160a01b038094169333851415806105d2575b6105a8578516801561057e578260005260209560978752604060002086600052875260406000205485811061055457859085600052609789526040600020886000528952036040600020558360005260978752604060002082600052875260406000206103bd8682546142ac565b90558186604051868152878a8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6260403392a43b6103f957005b6104569360008794604051968795869485937ff23a6e61000000000000000000000000000000000000000000000000000000009b8c865233600487015260248601526044850152606484015260a0608484015260a4830190613ed7565b03925af160009181610525575b506104eb575050600190610475614316565b6308c379a0146104b2575b50610488575b005b60046040517fefab6922000000000000000000000000000000000000000000000000000000008152fd5b6104ba614334565b90816104c65750610480565b6104e760405192839262461bcd60e51b845260048401526024830190613ed7565b0390fd5b7fffffffff0000000000000000000000000000000000000000000000000000000016149050610486576004604051633fbfe7f560e21b8152fd5b610546919250843d861161054d575b61053e8183613f80565b8101906142de565b9038610463565b503d610534565b60046040517fdd543d52000000000000000000000000000000000000000000000000000000008152fd5b60046040517f714fd844000000000000000000000000000000000000000000000000000000008152fd5b60046040517ff8ba8054000000000000000000000000000000000000000000000000000000008152fd5b5084600052609860205260406000203360005260205260ff604060002054161561034f565b600080fd5b346105f75760006003193601126105f757602060405160048152f35b346105f75760406003193601126105f75767ffffffffffffffff6004358181116105f75761064a903690600401613ff6565b6024358281116105f757610662903690600401613ff6565b3360009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf6508602090815260409091205491939091601216158015906101fe90610878575b501561085357600080526101c68252604060002090835190811161083d576106d082546144e3565b601f81116107f7575b5082601f821160011461076a57927f74b7c2afa3f89c562b59674a101e2c48bceeb27cdb620afefa14446f1ffa487b94928261075a9361074b9660009161075f575b506000198260011b9260031b1c19161790555b61073786614619565b604051938493604085526040850190613ed7565b90838203908401523395613ed7565b0390a2005b90508501518961071b565b601f1982169083600052846000209160005b8181106107e057508361074b96937f74b7c2afa3f89c562b59674a101e2c48bceeb27cdb620afefa14446f1ffa487b98969361075a96600194106107c7575b5050811b01905561072e565b87015160001960f88460031b161c1916905589806107bb565b91928660018192868b01518155019401920161077c565b8260005283600020601f830160051c810191858410610833575b601f0160051c01905b81811061082757506106d9565b6000815560010161081a565b9091508190610811565b634e487b7160e01b600052604160045260246000fd5b6064604051634baa2a4d60e01b81523360048201526000602482015260106044820152fd5b905060008052825260406000203360005282526012604060002054161515856106a8565b346105f75760406003193601126105f7576108b5613e88565b6108bd613e9e565b906001600160a01b03809116600052609860205260406000209116600052602052602060ff604060002054166040519015158152f35b346105f75760006003193601126105f75761092361090f6158e7565b604051918291602083526020830190613ed7565b0390f35b346105f75760206003193601126105f7576020610945600435615ccc565b6001600160a01b0360405191168152f35b346105f75760206003193601126105f7576004356000196101c854019080820361097c57005b604491604051917f4fa09b3f00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b346105f75760206003193601126105f75760043560005261012d60205260206001600160a01b0360406000205416604051908152f35b346105f75760606003193601126105f757600435610a04613e9e565b9060443567ffffffffffffffff81116105f757610a25903690600401613ff6565b90806000526101fe926020938085526040600020336000528552600a604060002054161590811591610ba6575b5015610b81576001600160a01b03610a6c91169182614942565b6040516301ffc9a760e01b81527f6890e5b30000000000000000000000000000000000000000000000000000000060048201528381602481855afa908115610b7557600091610b48575b5015610b1757816000929183858194519301915af190610ad46141fb565b9115610adc57005b6104e76040519283927fa5fa8d2b00000000000000000000000000000000000000000000000000000000845260048401526024830190613ed7565b602490604051907fe15b8e060000000000000000000000000000000000000000000000000000000082526004820152fd5b610b689150843d8611610b6e575b610b608183613f80565b8101906154bb565b84610ab6565b503d610b56565b6040513d6000823e3d90fd5b60648260405190634baa2a4d60e01b8252336004830152602482015260086044820152fd5b90506000805284526040600020336000528452600a60406000205416151585610a52565b346105f75760406003193601126105f757610be3613e88565b60243590610bf033614764565b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000602082019081526001600160a01b03831660248301526044808301859052825292906000908190610c46606482613f80565b516001600160a01b039582877f0000000000000000000000000000000000000000000000000000000000000000165af1610c7e6141fb565b5015610c8657005b606492604051927f424cf2e30000000000000000000000000000000000000000000000000000000084523360048501521660248301526044820152fd5b346105f75760406003193601126105f75760043567ffffffffffffffff81116105f757610d16610cf960209236906004016140f3565b90610d03336148aa565b610d0b6145c4565b3391602435916149c6565b6001606555604051908152f35b346105f7576003196080813601126105f757610d3d613e88565b67ffffffffffffffff6024358181116105f757610d5e90369060040161407a565b906044358181116105f757610d7790369060040161407a565b906064359081116105f757610d90903690600401613ff6565b90610d996145c4565b3360009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020908152604082205460061615969092915b8551811015610e0857610dea9088610def57614d93565b610dd3565b610e03610dfc8289614282565b5133614942565b614d93565b50908491866001600160a01b0390818116918215611157578551908551820361112d576101cb54168061109b575b5060005b8181106110585750508160006040517f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb339180610e788a8c836142b9565b0390a43b610f21575b505060005b8251811015610f1a5780610ee8610eb687610ea4610f159588614282565b51610eaf8588614282565b5190615799565b610ede610ec38488614282565b51610ed883610ed2878a614282565b516142ac565b906156fb565b610ed28386614282565b610ef28286614282565b516000526101c68652610f0e60026040600020019182546142ac565b9055614d93565b610e86565b6001606555005b84604051809281600081610f977fbc197c81000000000000000000000000000000000000000000000000000000009889835233600484015283602484015260a06044840152610f87610f778d60a4860190614095565b828582030160648601528c614095565b908382030160848401528d613ed7565b03925af160009181611039575b506110015750506001610fb5614316565b6308c379a014610fcc575b610488575b8480610e81565b610fd4614334565b80610fdf5750610fc0565b846104e760405192839262461bcd60e51b845260048401526024830190613ed7565b7fffffffff000000000000000000000000000000000000000000000000000000001614610fc5576004604051633fbfe7f560e21b8152fd5b611051919250863d881161054d5761053e8183613f80565b9087610fa4565b8061106560019288614282565b51611070828a614282565b5160005260978a526040600020866000528a5261109360406000209182546142ac565b905501610e3a565b803b156105f75760006110f0879289838861110f8f6110ff8d6040519a8b998a988997634058856760e11b89523060048a01523360248a01528960448a0152606489015260e0608489015260e4880190614095565b918683030160a4870152614095565b908d8483030160c4850152613ed7565b03925af18015610b755715610e365761112790613f50565b88610e36565b60046040517ff9532c39000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8113ddc8000000000000000000000000000000000000000000000000000000008152fd5b346105f75760806003193601126105f75761119a613e88565b6024356064359167ffffffffffffffff83116105f7576111c1610f1a933690600401613ff6565b916111ca6145c4565b6111d48133614942565b604435916154d3565b346105f75760006003193601126105f757602060405160028152f35b346105f75760206003193601126105f757610923611218600435615cff565b6040519182918291909160406001600160a01b0381606084019563ffffffff8082511686526020820151166020860152015116910152565b346105f75760806003193601126105f75760043560607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601126105f7576040519061129b82613efc565b63ffffffff60243581811681036105f757835260443581811681036105f7576020808501918252606435906001600160a01b0380831683036105f75760408701928352856000526101fe8083526040600020336000528352602260406000205416159081159161145a575b501561143657600185885116146113f457825116158061141e575b6113f4578460005261016081527fffffffff000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffff000000000000000067ffffffff000000006040600020968951169387549651901b16935160401b16931617171790557f5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d604051806113ef33958291909160406001600160a01b0381606084019563ffffffff8082511686526020820151166020860152015116910152565b0390a3005b60046040517f0d9b92f1000000000000000000000000000000000000000000000000000000008152fd5b50855184161515806113215750838351161515611321565b6064868360405191634baa2a4d60e01b835233600484015260248301526044820152fd5b90506000805282526040600020336000528252602260406000205416151588611306565b346105f7576020806003193601126105f75760043567ffffffffffffffff81116105f7576114b36114b9913690600401614121565b90615df8565b6040519082820192808352815180945260408301938160408260051b8601019301916000955b8287106114ec5785850386f35b909192938280611526837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08a600196030186528851613ed7565b96019201960195929190926114df565b346105f75760006003193601126105f757602060405160108152f35b346105f75760406003193601126105f75761156b613e88565b602435908115158092036105f7576001600160a01b0316908133146115df57336000526098602052604060002082600052602052604060002060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b60046040517fd67f41b2000000000000000000000000000000000000000000000000000000008152fd5b346105f75760006003193601126105f757604051604081019080821067ffffffffffffffff83111761083d5761092391604052600581527f312e342e300000000000000000000000000000000000000000000000000000006020820152604051918291602083526020830190613ed7565b60a06003193601126105f75761168e613e88565b6024359060443560643567ffffffffffffffff81116105f7576116b59036906004016140f3565b926084356001600160a01b039485821682036105f75761170b60009287611744956116de6145c4565b16976116ea8a8a614942565b6116f2614f3e565b8a86526102316020526040862054821691168834614f59565b9360405193849283927f6890e5b300000000000000000000000000000000000000000000000000000000845287898c3360048801614eff565b038183885af1918215610b755761176692869260009161179f575b5051615308565b6040519081523460208201527fb362243af1e2070d7d5bf8d713f2e0fab64203f1b71462afbe20572909788c5e60403392a46001606555005b6117bc91503d806000833e6117b48183613f80565b810190614dd7565b8761175f565b346105f75760406003193601126105f75760043560243567ffffffffffffffff81116105f7576000916001600160a01b0361181561180585943690600401613ff6565b926118108133614822565b615ccc565b1682602083519301915af16118286141fb565b901561183057005b6104e7906040519182917fa5fa8d2b000000000000000000000000000000000000000000000000000000008352602060048401526024830190613ed7565b346105f75760006003193601126105f75760405160208082528160605191828183015260005b8381106118b6575050601f19601f836000604080968601015201168101030190f35b6080810151858201604001528492508101611894565b346105f75760006003193601126105f7576020604051818152f35b346105f7576118f5366140c9565b916119008133614d30565b806000526101fe92836020526001600160a01b03604060002093169283600052602052604060002054179281600052602052604060002082600052602052826040600020557f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca600080a4005b346105f75760006003193601126105f75760206001600160a01b036101c95416604051908152f35b346105f75760206003193601126105f7576000604080516119b481613efc565b6060815282602082015201526004356000526101c660205261092360406000206002604051916119e383613efc565b6119ec8161451d565b8352600181015460208401520154604082015260405191829182614152565b346105f75760e06003193601126105f75760043567ffffffffffffffff81116105f757611a3c903690600401613ff6565b60243567ffffffffffffffff81116105f757611a5c903690600401613ff6565b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc3601126105f757604051611a9281613efc565b60443563ffffffff811681036105f757815260643563ffffffff811681036105f75760208201526084356001600160a01b03811681036105f75760408201526001600160a01b0360a4351660a435036105f75760c43567ffffffffffffffff81116105f757611b05903690600401614121565b9091611b0f6145c4565b60005493600885901c60ff1615801590611ffb575b80611fe3575b611fb957600160ff1986161760005560ff8560081c1615611f8a575b60ff60005460081c1615611f60576001606555611b6d6001600160a01b0360a43516615c65565b6101c89081549160018301905560405190611b8782613efc565b81526000602082015260006040820152816000526101c66020526040600020815180519067ffffffffffffffff821161083d578190611bc684546144e3565b601f8111611f10575b50602090601f8311600114611ea457600092611e99575b50506000198260011b9260031b1c19161781555b60208201516001820155600260408301519101557f5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe60405180611c3e339482614152565b0390a3600163ffffffff825116146113f4576001600160a01b036040820151161580611e76575b6113f45760ff94611d709160008052610160602052604060002063ffffffff82511681549067ffffffff00000000602085015160201b16907fffffffff000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffff0000000000000000604087015160401b169316171717905560007f5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d60405180611d4933958291909160406001600160a01b0381606084019563ffffffff8082511686526020820151166020860152015116910152565b0390a3611d606001600160a01b0360a43516615aed565b611d6b60a435615bc8565b614619565b80611de0575b505060081c1615611d88576001606555005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff600054166000557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a1610f1a565b611df291611ded33615c65565b615df8565b503360008181527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020526040812080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd169081905591907f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca8180a48280611d76565b50805163ffffffff16151580611c65575063ffffffff6020820151161515611c65565b015190508a80611be6565b9250836000526020600020906000935b601f1984168510611ef5576001945083601f19811610611edc575b505050811b018155611bfa565b015160001960f88460031b161c191690558a8080611ecf565b81810151835560209485019460019093019290910190611eb4565b909150836000526020600020601f840160051c810160208510611f59575b90849392915b601f830160051c82018110611f4a575050611bcf565b60008155859450600101611f34565b5080611f2e565b60046040517f96bfb100000000000000000000000000000000000000000000000000000000008152fd5b6101017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000861617600055611b46565b60046040517f7ab84482000000000000000000000000000000000000000000000000000000008152fd5b50303b151580611b2a5750600160ff86161415611b2a565b5060ff85161515611b24565b346105f75760606003193601126105f757612029604435602435600435615d7e565b604080516001600160a01b03939093168352602083019190915290f35b346105f75760206003193601126105f75760043560005261016060205260606040600020546001600160a01b036040519163ffffffff80821684528160201c16602084015260401c166040820152f35b346105f75760206003193601126105f7576004356001600160a01b0381168091036105f7576120c433614c98565b8061215e575b6101cb9073ffffffffffffffffffffffffffffffffffffffff1982541617905560026040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f3391806113ef819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b6040516301ffc9a760e01b8152634058856760e11b6004820152602081602481855afa908115610b75576000916121c6575b506120ca57602490604051907f17ce95600000000000000000000000000000000000000000000000000000000082526004820152fd5b6121de915060203d8111610b6e57610b608183613f80565b82612190565b346105f75760206003193601126105f75760043560005261023160205260206001600160a01b0360406000205416604051908152f35b346105f75760006003193601126105f75760c06101c9546101ca54906101cb5490604051926001600160a01b0391828116855260a01c6020850152818116604085015260a01c60608401528116608083015260a01c60a0820152f35b346105f75760006003193601126105f75760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346105f75760006003193601126105f75760206101c854604051908152f35b60806003193601126105f7576122ed613e88565b6024359060443560643567ffffffffffffffff81116105f7576123149036906004016140f3565b61231f9391936145c4565b6001600160a01b03809216936123358686614942565b34927f00000000000000000000000000000000000000000000000000000000000000009081166123a0575b506117449160009160405193849283927f6890e5b300000000000000000000000000000000000000000000000000000000845287898c3360048801614eff565b926123d56123ce867f00000000000000000000000000000000000000000000000000000000000000006143e4565b8092614f31565b93600080808085856201adb0f16123ea6141fb565b50156123f65750612360565b6040517f4b789d360000000000000000000000000000000000000000000000000000000081526001600160a01b039190911660048201526024810191909152604490fd5b346105f75760206003193601126105f757610923612459600435614422565b6040519182918291909160808060a0830194805184526020810151602085015260408101516040850152606081015160608501520151910152565b346105f7576003196060813601126105f7576124ae613e88565b67ffffffffffffffff6024358181116105f7576124cf903690600401614121565b9390916044359081116105f7576124ea903690600401614121565b926001600160a01b039586861695338714158061272a575b6126e8575061251f929161251791369161402c565b93369161402c565b9383156126be578251918551830361112d576040519161253e83613f64565b600083526101cb54169182612625575b50505060005b8181106125a05750507f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb6125926000946040519182913395836142b9565b0390a4610486604051613f64565b6125aa8184614282565b51906125b68187614282565b5182600052609760208181526040600020886000528152604060002054918383106125fb57600195600052815260406000209088600052520360406000205501612554565b60046040517f5f896ec2000000000000000000000000000000000000000000000000000000008152fd5b823b156105f757869285600088612699829661267a9661268a6040519a8b998a988997634058856760e11b89523060048a01523360248a0152604489015288606489015260e0608489015260e4880190614095565b90848783030160a4880152614095565b918483030160c4850152613ed7565b03925af18015610b75576126af575b808061254e565b6126b890613f50565b846126a8565b60046040517f45d40ad5000000000000000000000000000000000000000000000000000000008152fd5b6040517f839c23f20000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03919091166024820152604490fd5b5086600052609860205260406000203360005260205260ff6040600020541615612502565b346105f75760206003193601126105f7576004356000526101c760205260206001600160a01b0360406000205416604051908152f35b346105f75760606003193601126105f75760043567ffffffffffffffff81116105f7576127b69036906004016140f3565b90604435906001600160a01b0382168092036105f7576020926127dc91610d03336148aa565b9081600052610231835260406000209073ffffffffffffffffffffffffffffffffffffffff198254161790556001606555604051908152f35b346105f75760406003193601126105f7576004356024356001600160a01b0381168091036105f7576128456145c4565b61284f8233614822565b8160005260209061012d825260406000208173ffffffffffffffffffffffffffffffffffffffff1982541617905580612919575b6040513382857f5010f780a0de79bcfb9f3d6fec3cfe29758ef5c5800d575af709bc590bd78ade600080a4836128e557507f56e810c8cae84731149f628981d25769a084570b9ba6eebf3c32879e3dce56099250604051908152a16001606555005b604091506000837f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b948352820152a2610f1a565b6040516301ffc9a760e01b81527f7bc7e6460000000000000000000000000000000000000000000000000000000060048201528281602481855afa908115610b7557600091612999575b5061288357602490604051907fda755beb0000000000000000000000000000000000000000000000000000000082526004820152fd5b6129b09150833d8511610b6e57610b608183613f80565b84612963565b346105f75760006003193601126105f7576020610945614f3e565b346105f7576129df366140c9565b6129eb83929333614d30565b60008281526101fe602081815260408084206001600160a01b039788168086529083529084208054951990951694859055909491939092839083907f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca9080a4159182612b4b575b82612b26575b5050612a6057005b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09160006040926101c99283549373ffffffffffffffffffffffffffffffffffffffff1985169055845193168352820152a160006040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f3391806113ef819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b9091506000805282526040600020906000528152600260406000205416158380612a58565b6101c954851682149250612a52565b346105f75760206003193601126105f757610923612459600435614483565b346105f75760006003193601126105f7576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003612be45760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b60046040517f5e4c25f1000000000000000000000000000000000000000000000000000000008152fd5b60406003193601126105f757612c22613e88565b60243567ffffffffffffffff81116105f757612c42903690600401613ff6565b906001600160a01b03807f00000000000000000000000000000000000000000000000000000000000000001690813014612f0b577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc9080825416928303612ee1578392612cae33614c98565b6040517f21f743470000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201529316602484015260209283816044817f000000000000000000000000000000000000000000000000000000000000000086165afa908115610b7557600091612ec4575b50156105f7577f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612d64575050506104869150614181565b8316906040517f52d1902d0000000000000000000000000000000000000000000000000000000081528381600481865afa60009181612e95575b50612dcd5760046040517fe5ec1769000000000000000000000000000000000000000000000000000000008152fd5b03612e6b57612ddb83614181565b604051907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a2835115801590612e63575b612e1557005b823b15612e3b575082600092839261048695519201905af4612e356141fb565b906143a3565b807f369891e70000000000000000000000000000000000000000000000000000000060049252fd5b506001612e0f565b60046040517f8373ebf0000000000000000000000000000000000000000000000000000000008152fd5b9091508481813d8311612ebd575b612ead8183613f80565b810103126105f757519087612d9e565b503d612ea3565b612edb9150843d8611610b6e57610b608183613f80565b86612d27565b60046040517f64cd8d19000000000000000000000000000000000000000000000000000000008152fd5b60046040517f1932df45000000000000000000000000000000000000000000000000000000008152fd5b346105f75760406003193601126105f75760043567ffffffffffffffff8082116105f757366023830112156105f757816004013590612f7382614014565b92612f816040519485613f80565b82845260209260248486019160051b830101913683116105f757602401905b82821061307c575050506024359081116105f757612fc290369060040161407a565b8251908051820361305257612fd682614014565b93612fe46040519586613f80565b828552601f19612ff384614014565b01368587013760005b838110613016576040518581528061092381880189614095565b806130416001600160a01b0361302e60019486614282565b511661303a8387614282565b519061422b565b61304b8289614282565b5201612ffc565b60046040517f4ce4cfdc000000000000000000000000000000000000000000000000000000008152fd5b81356001600160a01b03811681036105f7578152908401908401612fa0565b346105f75760406003193601126105f7576130b4613e9e565b6004356000526101fe6020526001600160a01b03604060002091166000526020526020604060002054604051908152f35b346105f75760206003193601126105f7576602c2ad68fd900060043581810291811591830414171561311c57602090604051908152f35b634e487b7160e01b600052601160045260246000fd5b346105f75760006003193601126105f7573360009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf650860205260409020546022161515801561320e575b156131e957476001600160a01b03906101ca91600080808085858854166204baf0f16131a86141fb565b50156131b057005b604492541690604051917fa489930c00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b6064604051634baa2a4d60e01b81523360048201526000602482015260206044820152fd5b503360009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020526040902054602216151561317e565b346105f7576020806003193601126105f757613262613e88565b6001600160a01b0391827f000000000000000000000000000000000000000000000000000000000000000016803014612f0b577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc9084825416908103612ee157828461331a926132d133614c98565b6040517f21f743470000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201529116602482015291829081906044820190565b0381887f0000000000000000000000000000000000000000000000000000000000000000165afa908115610b7557600091613485575b50156105f7576040519361336385613f64565b600085527f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561339e575050506104869150614181565b8316906040517f52d1902d0000000000000000000000000000000000000000000000000000000081528381600481865afa60009181613456575b506134075760046040517fe5ec1769000000000000000000000000000000000000000000000000000000008152fd5b03612e6b5761341583614181565b604051907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a283511580159061344e57612e1557005b506000612e0f565b9091508481813d831161347e575b61346e8183613f80565b810103126105f7575190876133d8565b503d613464565b61349c9150833d8511610b6e57610b608183613f80565b85613350565b346105f75760031960a0813601126105f7576134bc613e88565b906134c5613e9e565b9167ffffffffffffffff6044358181116105f7576134e790369060040161407a565b916064358281116105f75761350090369060040161407a565b916084359081116105f757613519903690600401613ff6565b6001600160a01b038092169533871415806137e8575b6105a8578451845181036130525783821693841561057e576101cb541680613756575b5060005b8181106136d557505082876040517f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb3391806135938a8c836142b9565b0390a43b61359d57005b6000602094613617613608976135f894604051998a98899788967fbc197c81000000000000000000000000000000000000000000000000000000009e8f89523360048a0152602489015260a0604489015260a4880190614095565b9084878303016064880152614095565b91848303016084850152613ed7565b03925af1600091816136b5575b5061367d5750506001613635614316565b6308c379a014613646575b61048857005b61364e614334565b806136595750613640565b6104e79060405191829162461bcd60e51b8352602060048401526024830190613ed7565b7fffffffff000000000000000000000000000000000000000000000000000000001614610486576004604051633fbfe7f560e21b8152fd5b6136ce91925060203d811161054d5761053e8183613f80565b9083613624565b6136df8188614282565b51906136eb8188614282565b518260005260206097815260406000208c60005281526040600020549082821061055457846001956000526097825260406000208a600052825260406000206137358582546142ac565b9055600052609781526040600020908d600052520360406000205501613556565b803b156105f7576000876137aa9287838d6137ca8e6137ba8e6040519a8b998a988997634058856760e11b89523060048a01523360248a01526044890152606488015260e0608488015260e4870190614095565b90838683030160a4870152614095565b908382030160c48401528b613ed7565b03925af18015610b755715613552576137e290613f50565b88613552565b5086600052609860205260406000203360005260205260ff604060002054161561352f565b346105f75760406003193601126105f757613829600435615cff565b6001600160a01b03604061387361384c60243563ffffffff6020870151166143e4565b7f00000000000000000000000000000000000000000000000000000000000000009061578f565b9201511661092360405192839283602090939291936001600160a01b0360408201951681520152565b346105f75760606003193601126105f7576138b5613e88565b6024356000526101fe6020526001600160a01b03604060002091166000526020526020604435600217604060002054161515604051908152f35b346105f75760406003193601126105f75767ffffffffffffffff6004356024358281116105f757613924903690600401613ff6565b9161392f8233614822565b81156105f75760405191807f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b6020948581528061396e87820189613ed7565b0390a26000526101c68252604060002091835191821161083d5761399283546144e3565b601f8111613a3a575b5080601f83116001146139d757508192936000926139cc575b50506000198260011b9260031b1c1916179055600080f35b0151905083806139b4565b90601f198316948460005282600020926000905b878210613a22575050836001959610613a09575b505050811b019055005b015160001960f88460031b161c191690558380806139ff565b806001859682949686015181550195019301906139eb565b8360005281600020601f840160051c810191838510613a76575b601f0160051c01905b818110613a6a575061399b565b60008155600101613a5d565b9091508190613a54565b346105f75760006003193601126105f757602060405160088152f35b346105f75760406003193601126105f757600435613ab8613e9e565b9080600052610231806020526001600160a01b039182604060002054163303613b09576000526020526040600020911673ffffffffffffffffffffffffffffffffffffffff19825416179055600080f35b60046040517f2afb0ecf000000000000000000000000000000000000000000000000000000008152fd5b346105f75760206003193601126105f757613b4c613e88565b613b5533614c98565b6001600160a01b03811660009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf6508602052604090205460021615613b9e5761048690615aed565b60046040517f98ee9d38000000000000000000000000000000000000000000000000000000008152fd5b346105f75760006003193601126105f75760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346105f75760206003193601126105f757610486613c1f613e88565b613c2833614764565b615bc8565b346105f75760206003193601126105f75761092361090f600435615a62565b346105f75760006003193601126105f75760405160006101938054613c70816144e3565b80855291600191808316908115613cf65750600114613c9a575b6109238561090f81870382613f80565b600090815292507ffc8af01f449989052b52093a58fc9f42d0b11f0c6dd5dca0463dab62346ccc685b828410613cde57505050810160200161090f82610923613c8a565b80546020858701810191909152909301928101613cc3565b8695506109239693506020925061090f94915060ff191682840152151560051b8201019293613c8a565b346105f75760206003193601126105f7576004357fffffffff0000000000000000000000000000000000000000000000000000000081168091036105f757807f2a55205a0000000000000000000000000000000000000000000000000000000060209214908115613e13575b8115613d9e575b506040519015158152f35b7fd9b67a2600000000000000000000000000000000000000000000000000000000811491508115613de9575b8115613dd8575b5082613d93565b6301ffc9a760e01b91501482613dd1565b7f0e89341c0000000000000000000000000000000000000000000000000000000081149150613dca565b7f2920ca160000000000000000000000000000000000000000000000000000000081149150613d8c565b346105f75760006003193601126105f757602060405160008152f35b346105f75760406003193601126105f7576020613e80613e77613e88565b6024359061422b565b604051908152f35b600435906001600160a01b03821682036105f757565b602435906001600160a01b03821682036105f757565b60005b838110613ec75750506000910152565b8181015183820152602001613eb7565b90601f19601f602093613ef581518092818752878088019101613eb4565b0116010190565b6060810190811067ffffffffffffffff82111761083d57604052565b60a0810190811067ffffffffffffffff82111761083d57604052565b6040810190811067ffffffffffffffff82111761083d57604052565b67ffffffffffffffff811161083d57604052565b6020810190811067ffffffffffffffff82111761083d57604052565b90601f601f19910116810190811067ffffffffffffffff82111761083d57604052565b67ffffffffffffffff811161083d57601f01601f191660200190565b929192613fcb82613fa3565b91613fd96040519384613f80565b8294818452818301116105f7578281602093846000960137010152565b9080601f830112156105f75781602061401193359101613fbf565b90565b67ffffffffffffffff811161083d5760051b60200190565b929161403782614014565b916140456040519384613f80565b829481845260208094019160051b81019283116105f757905b82821061406b5750505050565b8135815290830190830161405e565b9080601f830112156105f7578160206140119335910161402c565b90815180825260208080930193019160005b8281106140b5575050505090565b8351855293810193928101926001016140a7565b60031960609101126105f757600435906024356001600160a01b03811681036105f7579060443590565b9181601f840112156105f75782359167ffffffffffffffff83116105f757602083818601950101116105f757565b9181601f840112156105f75782359167ffffffffffffffff83116105f7576020808501948460051b0101116105f757565b602081526060604061416f84518360208601526080850190613ed7565b93602081015182850152015191015290565b803b156141d1576001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc911673ffffffffffffffffffffffffffffffffffffffff19825416179055565b60046040517f529880eb000000000000000000000000000000000000000000000000000000008152fd5b3d15614226573d9061420c82613fa3565b9161421a6040519384613f80565b82523d6000602084013e565b606090565b6001600160a01b031690811561425857600052609760205260406000209060005260205260406000205490565b60046040517f8620cc34000000000000000000000000000000000000000000000000000000008152fd5b80518210156142965760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b9190820180921161311c57565b90916142d061401193604084526040840190614095565b916020818403910152614095565b908160209103126105f757517fffffffff00000000000000000000000000000000000000000000000000000000811681036105f75790565b60009060033d1161432357565b905060046000803e60005160e01c90565b600060443d106140115760405160031991823d016004833e815167ffffffffffffffff918282113d6024840111176143925781840194855193841161439a573d85010160208487010111614392575061401192910160200190613f80565b949350505050565b50949350505050565b156143ab5790565b8051156143ba57805190602001fd5b60046040517fa1451936000000000000000000000000000000000000000000000000000000008152fd5b8181029291811591840414171561311c57565b6040519061440482613f18565b60006080838281528260208201528260408201528260608201520152565b61442a6143f7565b5066012edc9ab5d00090818102918115908284041481171561311c576564f43391f00080830292830414171561311c576040519161446783613f18565b8252806020830152806040830152806060830152608082015290565b61448b6143f7565b5065c9e86723e000808202908215908383041481171561311c576564f43391f00080840293840414171561311c57604051916144c683613f18565b600083528160208401528160408401526060830152608082015290565b90600182811c92168015614513575b60208310146144fd57565b634e487b7160e01b600052602260045260246000fd5b91607f16916144f2565b9060405191826000825492614531846144e3565b9081845260019485811690816000146145a0575060011461455d575b505061455b92500383613f80565b565b9093915060005260209081600020936000915b81831061458857505061455b9350820101388061454d565b85548884018501529485019487945091830191614570565b905061455b95506020935060ff1991501682840152151560051b820101388061454d565b6002606554146145d5576002606555565b606460405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b90815167ffffffffffffffff811161083d576101939061463982546144e3565b601f81116146ff575b50602080601f831160011461467e575081929394600092614673575b50506000198260011b9260031b1c1916179055565b01519050388061465e565b90601f19831695846000527ffc8af01f449989052b52093a58fc9f42d0b11f0c6dd5dca0463dab62346ccc68926000905b8882106146e7575050836001959697106146ce575b505050811b019055565b015160001960f88460031b161c191690553880806146c4565b806001859682949686015181550195019301906146af565b60008381527ffc8af01f449989052b52093a58fc9f42d0b11f0c6dd5dca0463dab62346ccc68601f840160051c8101926020851061475a575b601f0160051c01915b82811061474f575050614642565b818155600101614741565b9092508290614738565b6001600160a01b03811660009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020526040902054602216151580156147df575b156147b05750565b6064906001600160a01b0360405191634baa2a4d60e01b83521660048201526000602482015260206044820152fd5b506001600160a01b03811660009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf6508602052604090205460221615156147a8565b9060008181526101fe90816020526001600160a01b036040822094169384825260205260126040822054161591821592614887575b505015614862575050565b6064925060405191634baa2a4d60e01b83526004830152602482015260106044820152fd5b601292509060409181805260205281812085825260205220541615153880614857565b6001600160a01b031660008181527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020526040812054600616158015906101fe90614920575b50156148fb575050565b6064925060405191634baa2a4d60e01b83526004830152602482015260046044820152fd5b90508180526020526040812082825260205260066040822054161515386148f1565b9060008181526101fe90816020526001600160a01b036040822094169384825260205260066040822054161591821592614982575b5050156148fb575050565b600692509060409181805260205281812085825260205220541615153880614977565b601f8260209493601f19938186528686013760008582860101520116010190565b93929091936149d6368483613fbf565b906101c893845494600186019055604051926149f184613efc565b835286602084015260006040840152846000526101c6602052604060002096835197885167ffffffffffffffff811161083d57614a2e82546144e3565b99601f8b11614c54575b88999a5060009896979850602090601f8311600114614bbf579180889993927f1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc068999593600092614bb4575b50506000198260011b9260031b1c19161781555b60208201516001820155600260408301519101557f5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe60405180614adb339482614152565b0390a3846000526101fe806020526001600160a01b0360406000209716968760005260205260026040600020541790866000526020526040600020876000526020528060406000205586867f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca600080a481614b74575b614b686040519384936040855260408501916149a5565b9060208301520390a390565b847f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b6040516020815280614bac6020820187896149a5565b0390a2614b51565b015190503880614a83565b979291908260005260206000209860005b601f1984168110614c3957509188996001927f1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc0689a96959483601f19811610614c20575b505050811b018155614a97565b015160001960f88460031b161c19169055388080614c13565b828201518b556001909a01998c995060209283019201614bd0565b826000526020600020601f830160051c810160208410614c91575b601f8d0160051c82018110614c85575050614a38565b60008155600101614c6f565b5080614c6f565b6001600160a01b031660008181527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020526040812054600216158015906101fe90614d0e575b5015614ce9575050565b6064925060405191634baa2a4d60e01b83526004830152602482015260026044820152fd5b9050818052602052604081208282526020526002604082205416151538614cdf565b9060008181526101fe90816020526001600160a01b036040822094169384825260205260026040822054161591821592614d70575b505015614ce9575050565b600292509060409181805260205281812085825260205220541615153880614d65565b600019811461311c5760010190565b90929192614daf81613fa3565b91614dbd6040519384613f80565b8294828452828201116105f757602061455b930190613eb4565b60209081818403126105f757805167ffffffffffffffff918282116105f757019060409081838603126105f757815194614e1086613f34565b83518281116105f75784019181601f840112156105f757825190614e3382614014565b94614e4081519687613f80565b828652878087019360051b860101948486116105f757908189809998979695949301935b868510614e7d5750505050505050845201519082015290565b9091929380959697989950518481116105f75782019083601f1983890301126105f757835191614eac83613f34565b8b81015160038110156105f757835284810151908682116105f757019087603f830112156105f7578b92614ee889848887809701519101614da2565b838201528152019401929190899897969594614e64565b919260a0936001600160a01b0361401198969316845260208401526040830152606082015281608082015201916149a5565b9190820391821161311c57565b6101ca546001600160a01b03168015614f545790565b503090565b909194939460009283946602c2ad68fd9000938483029483860414831517156152c05784811015614fae5760046040517fede1d8dc000000000000000000000000000000000000000000000000000000008152fd5b80850361513657508093614fc28993614422565b986001600160a01b038093161561510e575b8216156150e6575b817f000000000000000000000000000000000000000000000000000000000000000016928951948a6020810151926080606060408401519301519d015193873b156150e25791868094928c9d9e9f948260409e9d9e519e8f9d8e9c8d987ffaa3516f000000000000000000000000000000000000000000000000000000008a521660048199015260248d01521660448b015260648a015216608488015260a487015260c486015260e48501527f0000000000000000000000000000000000000000000000000000000000000000166101048401526101248301525a9261014493f180156150d7576150cc57505090565b614011919250613f50565b6040513d84823e3d90fd5b8a80fd5b7f00000000000000000000000000000000000000000000000000000000000000009250614fdc565b7f00000000000000000000000000000000000000000000000000000000000000009550614fd4565b955091908297949396979261514b8692614483565b906001600160a01b03968780921615615298575b1615615270575b857f000000000000000000000000000000000000000000000000000000000000000016926020820151926040830151906080606085015194015194863b1561526c57928897969594928a80959381946040519d8e9b7ffaa3516f000000000000000000000000000000000000000000000000000000008d528d8d816004820152602401521660448c015260648b015216608489015260a48801521660c486015260e48501527f00000000000000000000000000000000000000000000000000000000000000001661010484015261012483015281875a9261014493f1908115615260575061525357500390565b61525c90613f50565b0390565b604051903d90823e3d90fd5b8880fd5b7f00000000000000000000000000000000000000000000000000000000000000009150615166565b7f0000000000000000000000000000000000000000000000000000000000000000955061515f565b602486634e487b7160e01b81526011600452fd5b600311156152de57565b634e487b7160e01b600052602160045260246000fd5b51906001600160a01b03821682036105f757565b929160005b84518110156154b4576153208186614282565b515161532b816152d4565b615334816152d4565b600181036153f7575060208061534a8388614282565b51015160409182828051810103126105f757615368839183016152f4565b910151908186116153ce5760008080936001600160a01b038294166204baf0f16153906141fb565b50156153a557506153a090614d93565b61530d565b600490517fe373ab5c000000000000000000000000000000000000000000000000000000008152fd5b600483517f644f3cdc000000000000000000000000000000000000000000000000000000008152fd5b806154036002926152d4565b036154ab576020806154158388614282565b51015160609182828051810103126105f7576154329082016152f4565b9160409081830151920151918580151591826154a0575b50506154775791610e0391856001600160a01b036153a09695519361546d85613f64565b60008552166154d3565b600490517f4cdcfbf9000000000000000000000000000000000000000000000000000000008152fd5b141590508538615449565b6153a090614d93565b5050509050565b908160209103126105f7575180151581036105f75790565b9092916155036155089382866154ea838383615799565b956154fe6154f888856142ac565b836156fb565b615529565b6142ac565b906000526101c660205261552560026040600020019182546142ac565b9055565b9291906001600160a01b0384168015611157576000928284526020946097865260409687862084875287528786206155628482546142ac565b905583868951878152858a8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628b3392a43b6155a4575b50505050505050565b6155ff9286928689518096819582947ff23a6e61000000000000000000000000000000000000000000000000000000009a8b85523360048601528560248601526044850152606484015260a0608484015260a4830190613ed7565b03925af18391816156dc575b5061569b57505060019161561d614316565b6308c379a014615665575b505061563c57505b3880808080808061559b565b600490517fefab6922000000000000000000000000000000000000000000000000000000008152fd5b61566d614334565b91826156795750615628565b846104e791505192839262461bcd60e51b845260048401526024830190613ed7565b7fffffffff00000000000000000000000000000000000000000000000000000000160391506156cc90505750615630565b60049051633fbfe7f560e21b8152fd5b6156f4919250853d871161054d5761053e8183613f80565b903861560b565b90816000526101c6602052604060002090600282015490600161571e82846142ac565b93015480931161572e5750505050565b60849450604051937f1255c8fd0000000000000000000000000000000000000000000000000000000085526004850152602484015260448301526064820152fd5b8115615779570690565b634e487b7160e01b600052601260045260246000fd5b8115615779570490565b92919092600093818552610160948560205263ffffffff916040928084842054169081156158a0575b508015615896578483526101c6602052600184842001549060028585200154906157f56157ef828461576f565b856142ac565b60001982019182116152c057916158136158199261581f959461578f565b946142ac565b90614f31565b8082101561588e5750955b86615837575b5050505050565b8382526020526001600160a01b038083832054841c1692831561587b575b50821615615874575061586a92918591615529565b3880808080615830565b9450505050565b82805280832054901c8116925038615855565b90509561582a565b5090955050505050565b90508280528383205416386157c2565b6020818303126105f75780519067ffffffffffffffff82116105f757019080601f830112156105f757815161401192602001614da2565b6000805261012d6020527fa581b17bfc4d6578e300cafbf34fd2dc1fef0270d8c73f88a99dcde2859a6639546001600160a01b039081168015615992575b168061593457506140116159a0565b6000600491604051928380927fe8a3d4850000000000000000000000000000000000000000000000000000000082525afa908115610b7557600091615977575090565b614011913d8091833e61598a8183613f80565b8101906158b0565b508060406000205416615925565b60008080526101c690816020526040916159bc838320546144e3565b615a52575080805261012d6020526001600160a01b0390808284822054168015615a46575b60248551809581937f0e89341c000000000000000000000000000000000000000000000000000000008352856004840152165afa928315615a3c57508092615a2857505090565b61401192503d8091833e61598a8183613f80565b51903d90823e3d90fd5b508284822054166159e1565b818052602052206140119061451d565b6000908082526101c680602052615a7c60408420546144e3565b615ada5750816001600160a01b03615a9383615ccc565b16916024604051809481937f0e89341c00000000000000000000000000000000000000000000000000000000835260048301525afa918215615260578092615a2857505090565b916140119260409282526020522061451d565b6101c980546001600160a01b0392831673ffffffffffffffffffffffffffffffffffffffff19821681179092556040805193909116835260208301919091527f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a160006040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f339180615bc3819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b0390a3565b6001600160a01b036101ca911673ffffffffffffffffffffffffffffffffffffffff1982541617905560016040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f339180615bc3819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b6001600160a01b031660008181527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020526040812080546002179081905591907f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca8180a4565b60005261012d6020526001600160a01b03908160406000205416918215615cf05750565b60008080526040902054169150565b6040805191615d0d83613efc565b600090818452818360209582878201520152815281610160918285526001600160a01b03928383832054841c16615d6f5781805285522092825193615d5185613efc565b549063ffffffff808316865282821c1690850152821c169082015290565b502092825193615d5185613efc565b615d8a90939293615cff565b9263ffffffff9182855116908115615ddf57615db09291615daa9161576f565b906142ac565b90600019818551160181811161311c576001600160a01b0392604092615dd792169061578f565b930151169190565b505050509060406001600160a01b039101511690600090565b9190615e0381614014565b90604091615e1383519182613f80565b818152601f19615e2283614014565b0160005b818110615f3e575050809460005b838110615e42575050505050565b8060051b8201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1833603018112156105f75782019081359167ffffffffffffffff83116105f75760208091019083360382136105f757600080615eae615f1e94615f39973691613fbf565b8a5193615eba85613efc565b602785527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c818601527f206661696c6564000000000000000000000000000000000000000000000000008c86015281519101305af4615f176141fb565b9030615f4f565b615f288286614282565b52615f338185614282565b50614d93565b615e34565b806060602080938601015201615e26565b91929015615fb05750815115615f63575090565b3b15615f6c5790565b606460405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156136595750805190602001fdfea26469706673582212209d661661ec61b1198babb33ada415cf81d60c9ed199bd8d15eac67510139096b64736f6c634300081100330000000000000000000000000000000000000000000000000002c2ad68fd9000000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d0000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb850000000000000000000000007777777f279eba3d3ad8f4e708545291a6fdba8b
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c8062fdd58e14613e595780630114420114613e3d57806301ffc9a714613d2057806306fdde0314613c4c5780630e89341c14613c2d57806310a7eb5d14613c0357806313966db514613bc857806313af403514613b3357806317bd48bb14613a9c57806318711c7d14613a8057806318e97fd1146138ef57806323bd03861461389c5780632a55205a1461380d5780632eb2c2d6146134a2578063300ecdb91461309b5780633659cfe6146132485780633ccfd60b146131325780634132239b146130e55780634913162d1461309b5780634e1273f414612f355780634f1ef28614612c0e57806352d1902d14612b795780635c04608414612b5a5780635d0f6cba146129d157806364ea3835146129b65780636661a9ba14612815578063674cbae61461278557806369a5b3021461274f5780636b20c45414612494578063722933f71461243a578063731133e9146122d957806375794a3c146122ba578063765b0c361461227657806379502c551461221a5780637dafae4d146121e45780637f2dc61c146120965780637f77f574146120465780638621ea4b146120075780638a08eb4c14611a0b5780638c7a63ae146119945780638da5cb5b1461196c5780638ec998a0146118e7578063929a7128146118cc57806395d89b411461186e5780639c5c63c9146117c25780639dbb844d1461167a578063a0a8e46014611609578063a22cb46514611552578063a453eaf014611536578063ac9650d81461147e578063afed7e9e14611250578063bb3bafd6146111f9578063c0464356146111dd578063c238d1ee14611181578063d1ad846b14610d23578063d258609a14610cc3578063d6ef7af014610bca578063d904b94a146109e8578063dd15e05f146109b2578063e72878b414610956578063e74d86c214610927578063e8a3d485146108f3578063e985e9c51461089c578063ef71c82e14610618578063f1b0d6bb146105fc5763f242432a146102f157600080fd5b346105f75760a06003193601126105f75761030a613e88565b610312613e9e565b9060643560443560843567ffffffffffffffff81116105f757610339903690600401613ff6565b6001600160a01b038094169333851415806105d2575b6105a8578516801561057e578260005260209560978752604060002086600052875260406000205485811061055457859085600052609789526040600020886000528952036040600020558360005260978752604060002082600052875260406000206103bd8682546142ac565b90558186604051868152878a8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6260403392a43b6103f957005b6104569360008794604051968795869485937ff23a6e61000000000000000000000000000000000000000000000000000000009b8c865233600487015260248601526044850152606484015260a0608484015260a4830190613ed7565b03925af160009181610525575b506104eb575050600190610475614316565b6308c379a0146104b2575b50610488575b005b60046040517fefab6922000000000000000000000000000000000000000000000000000000008152fd5b6104ba614334565b90816104c65750610480565b6104e760405192839262461bcd60e51b845260048401526024830190613ed7565b0390fd5b7fffffffff0000000000000000000000000000000000000000000000000000000016149050610486576004604051633fbfe7f560e21b8152fd5b610546919250843d861161054d575b61053e8183613f80565b8101906142de565b9038610463565b503d610534565b60046040517fdd543d52000000000000000000000000000000000000000000000000000000008152fd5b60046040517f714fd844000000000000000000000000000000000000000000000000000000008152fd5b60046040517ff8ba8054000000000000000000000000000000000000000000000000000000008152fd5b5084600052609860205260406000203360005260205260ff604060002054161561034f565b600080fd5b346105f75760006003193601126105f757602060405160048152f35b346105f75760406003193601126105f75767ffffffffffffffff6004358181116105f75761064a903690600401613ff6565b6024358281116105f757610662903690600401613ff6565b3360009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf6508602090815260409091205491939091601216158015906101fe90610878575b501561085357600080526101c68252604060002090835190811161083d576106d082546144e3565b601f81116107f7575b5082601f821160011461076a57927f74b7c2afa3f89c562b59674a101e2c48bceeb27cdb620afefa14446f1ffa487b94928261075a9361074b9660009161075f575b506000198260011b9260031b1c19161790555b61073786614619565b604051938493604085526040850190613ed7565b90838203908401523395613ed7565b0390a2005b90508501518961071b565b601f1982169083600052846000209160005b8181106107e057508361074b96937f74b7c2afa3f89c562b59674a101e2c48bceeb27cdb620afefa14446f1ffa487b98969361075a96600194106107c7575b5050811b01905561072e565b87015160001960f88460031b161c1916905589806107bb565b91928660018192868b01518155019401920161077c565b8260005283600020601f830160051c810191858410610833575b601f0160051c01905b81811061082757506106d9565b6000815560010161081a565b9091508190610811565b634e487b7160e01b600052604160045260246000fd5b6064604051634baa2a4d60e01b81523360048201526000602482015260106044820152fd5b905060008052825260406000203360005282526012604060002054161515856106a8565b346105f75760406003193601126105f7576108b5613e88565b6108bd613e9e565b906001600160a01b03809116600052609860205260406000209116600052602052602060ff604060002054166040519015158152f35b346105f75760006003193601126105f75761092361090f6158e7565b604051918291602083526020830190613ed7565b0390f35b346105f75760206003193601126105f7576020610945600435615ccc565b6001600160a01b0360405191168152f35b346105f75760206003193601126105f7576004356000196101c854019080820361097c57005b604491604051917f4fa09b3f00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b346105f75760206003193601126105f75760043560005261012d60205260206001600160a01b0360406000205416604051908152f35b346105f75760606003193601126105f757600435610a04613e9e565b9060443567ffffffffffffffff81116105f757610a25903690600401613ff6565b90806000526101fe926020938085526040600020336000528552600a604060002054161590811591610ba6575b5015610b81576001600160a01b03610a6c91169182614942565b6040516301ffc9a760e01b81527f6890e5b30000000000000000000000000000000000000000000000000000000060048201528381602481855afa908115610b7557600091610b48575b5015610b1757816000929183858194519301915af190610ad46141fb565b9115610adc57005b6104e76040519283927fa5fa8d2b00000000000000000000000000000000000000000000000000000000845260048401526024830190613ed7565b602490604051907fe15b8e060000000000000000000000000000000000000000000000000000000082526004820152fd5b610b689150843d8611610b6e575b610b608183613f80565b8101906154bb565b84610ab6565b503d610b56565b6040513d6000823e3d90fd5b60648260405190634baa2a4d60e01b8252336004830152602482015260086044820152fd5b90506000805284526040600020336000528452600a60406000205416151585610a52565b346105f75760406003193601126105f757610be3613e88565b60243590610bf033614764565b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000602082019081526001600160a01b03831660248301526044808301859052825292906000908190610c46606482613f80565b516001600160a01b039582877f0000000000000000000000007777777f279eba3d3ad8f4e708545291a6fdba8b165af1610c7e6141fb565b5015610c8657005b606492604051927f424cf2e30000000000000000000000000000000000000000000000000000000084523360048501521660248301526044820152fd5b346105f75760406003193601126105f75760043567ffffffffffffffff81116105f757610d16610cf960209236906004016140f3565b90610d03336148aa565b610d0b6145c4565b3391602435916149c6565b6001606555604051908152f35b346105f7576003196080813601126105f757610d3d613e88565b67ffffffffffffffff6024358181116105f757610d5e90369060040161407a565b906044358181116105f757610d7790369060040161407a565b906064359081116105f757610d90903690600401613ff6565b90610d996145c4565b3360009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020908152604082205460061615969092915b8551811015610e0857610dea9088610def57614d93565b610dd3565b610e03610dfc8289614282565b5133614942565b614d93565b50908491866001600160a01b0390818116918215611157578551908551820361112d576101cb54168061109b575b5060005b8181106110585750508160006040517f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb339180610e788a8c836142b9565b0390a43b610f21575b505060005b8251811015610f1a5780610ee8610eb687610ea4610f159588614282565b51610eaf8588614282565b5190615799565b610ede610ec38488614282565b51610ed883610ed2878a614282565b516142ac565b906156fb565b610ed28386614282565b610ef28286614282565b516000526101c68652610f0e60026040600020019182546142ac565b9055614d93565b610e86565b6001606555005b84604051809281600081610f977fbc197c81000000000000000000000000000000000000000000000000000000009889835233600484015283602484015260a06044840152610f87610f778d60a4860190614095565b828582030160648601528c614095565b908382030160848401528d613ed7565b03925af160009181611039575b506110015750506001610fb5614316565b6308c379a014610fcc575b610488575b8480610e81565b610fd4614334565b80610fdf5750610fc0565b846104e760405192839262461bcd60e51b845260048401526024830190613ed7565b7fffffffff000000000000000000000000000000000000000000000000000000001614610fc5576004604051633fbfe7f560e21b8152fd5b611051919250863d881161054d5761053e8183613f80565b9087610fa4565b8061106560019288614282565b51611070828a614282565b5160005260978a526040600020866000528a5261109360406000209182546142ac565b905501610e3a565b803b156105f75760006110f0879289838861110f8f6110ff8d6040519a8b998a988997634058856760e11b89523060048a01523360248a01528960448a0152606489015260e0608489015260e4880190614095565b918683030160a4870152614095565b908d8483030160c4850152613ed7565b03925af18015610b755715610e365761112790613f50565b88610e36565b60046040517ff9532c39000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8113ddc8000000000000000000000000000000000000000000000000000000008152fd5b346105f75760806003193601126105f75761119a613e88565b6024356064359167ffffffffffffffff83116105f7576111c1610f1a933690600401613ff6565b916111ca6145c4565b6111d48133614942565b604435916154d3565b346105f75760006003193601126105f757602060405160028152f35b346105f75760206003193601126105f757610923611218600435615cff565b6040519182918291909160406001600160a01b0381606084019563ffffffff8082511686526020820151166020860152015116910152565b346105f75760806003193601126105f75760043560607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601126105f7576040519061129b82613efc565b63ffffffff60243581811681036105f757835260443581811681036105f7576020808501918252606435906001600160a01b0380831683036105f75760408701928352856000526101fe8083526040600020336000528352602260406000205416159081159161145a575b501561143657600185885116146113f457825116158061141e575b6113f4578460005261016081527fffffffff000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffff000000000000000067ffffffff000000006040600020968951169387549651901b16935160401b16931617171790557f5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d604051806113ef33958291909160406001600160a01b0381606084019563ffffffff8082511686526020820151166020860152015116910152565b0390a3005b60046040517f0d9b92f1000000000000000000000000000000000000000000000000000000008152fd5b50855184161515806113215750838351161515611321565b6064868360405191634baa2a4d60e01b835233600484015260248301526044820152fd5b90506000805282526040600020336000528252602260406000205416151588611306565b346105f7576020806003193601126105f75760043567ffffffffffffffff81116105f7576114b36114b9913690600401614121565b90615df8565b6040519082820192808352815180945260408301938160408260051b8601019301916000955b8287106114ec5785850386f35b909192938280611526837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08a600196030186528851613ed7565b96019201960195929190926114df565b346105f75760006003193601126105f757602060405160108152f35b346105f75760406003193601126105f75761156b613e88565b602435908115158092036105f7576001600160a01b0316908133146115df57336000526098602052604060002082600052602052604060002060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b60046040517fd67f41b2000000000000000000000000000000000000000000000000000000008152fd5b346105f75760006003193601126105f757604051604081019080821067ffffffffffffffff83111761083d5761092391604052600581527f312e342e300000000000000000000000000000000000000000000000000000006020820152604051918291602083526020830190613ed7565b60a06003193601126105f75761168e613e88565b6024359060443560643567ffffffffffffffff81116105f7576116b59036906004016140f3565b926084356001600160a01b039485821682036105f75761170b60009287611744956116de6145c4565b16976116ea8a8a614942565b6116f2614f3e565b8a86526102316020526040862054821691168834614f59565b9360405193849283927f6890e5b300000000000000000000000000000000000000000000000000000000845287898c3360048801614eff565b038183885af1918215610b755761176692869260009161179f575b5051615308565b6040519081523460208201527fb362243af1e2070d7d5bf8d713f2e0fab64203f1b71462afbe20572909788c5e60403392a46001606555005b6117bc91503d806000833e6117b48183613f80565b810190614dd7565b8761175f565b346105f75760406003193601126105f75760043560243567ffffffffffffffff81116105f7576000916001600160a01b0361181561180585943690600401613ff6565b926118108133614822565b615ccc565b1682602083519301915af16118286141fb565b901561183057005b6104e7906040519182917fa5fa8d2b000000000000000000000000000000000000000000000000000000008352602060048401526024830190613ed7565b346105f75760006003193601126105f75760405160208082528160605191828183015260005b8381106118b6575050601f19601f836000604080968601015201168101030190f35b6080810151858201604001528492508101611894565b346105f75760006003193601126105f7576020604051818152f35b346105f7576118f5366140c9565b916119008133614d30565b806000526101fe92836020526001600160a01b03604060002093169283600052602052604060002054179281600052602052604060002082600052602052826040600020557f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca600080a4005b346105f75760006003193601126105f75760206001600160a01b036101c95416604051908152f35b346105f75760206003193601126105f7576000604080516119b481613efc565b6060815282602082015201526004356000526101c660205261092360406000206002604051916119e383613efc565b6119ec8161451d565b8352600181015460208401520154604082015260405191829182614152565b346105f75760e06003193601126105f75760043567ffffffffffffffff81116105f757611a3c903690600401613ff6565b60243567ffffffffffffffff81116105f757611a5c903690600401613ff6565b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc3601126105f757604051611a9281613efc565b60443563ffffffff811681036105f757815260643563ffffffff811681036105f75760208201526084356001600160a01b03811681036105f75760408201526001600160a01b0360a4351660a435036105f75760c43567ffffffffffffffff81116105f757611b05903690600401614121565b9091611b0f6145c4565b60005493600885901c60ff1615801590611ffb575b80611fe3575b611fb957600160ff1986161760005560ff8560081c1615611f8a575b60ff60005460081c1615611f60576001606555611b6d6001600160a01b0360a43516615c65565b6101c89081549160018301905560405190611b8782613efc565b81526000602082015260006040820152816000526101c66020526040600020815180519067ffffffffffffffff821161083d578190611bc684546144e3565b601f8111611f10575b50602090601f8311600114611ea457600092611e99575b50506000198260011b9260031b1c19161781555b60208201516001820155600260408301519101557f5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe60405180611c3e339482614152565b0390a3600163ffffffff825116146113f4576001600160a01b036040820151161580611e76575b6113f45760ff94611d709160008052610160602052604060002063ffffffff82511681549067ffffffff00000000602085015160201b16907fffffffff000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffff0000000000000000604087015160401b169316171717905560007f5837d55897cfc337f160a71d7b63a047abd50a3a8834f1c5d70f338846358c6d60405180611d4933958291909160406001600160a01b0381606084019563ffffffff8082511686526020820151166020860152015116910152565b0390a3611d606001600160a01b0360a43516615aed565b611d6b60a435615bc8565b614619565b80611de0575b505060081c1615611d88576001606555005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff600054166000557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a1610f1a565b611df291611ded33615c65565b615df8565b503360008181527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020526040812080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd169081905591907f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca8180a48280611d76565b50805163ffffffff16151580611c65575063ffffffff6020820151161515611c65565b015190508a80611be6565b9250836000526020600020906000935b601f1984168510611ef5576001945083601f19811610611edc575b505050811b018155611bfa565b015160001960f88460031b161c191690558a8080611ecf565b81810151835560209485019460019093019290910190611eb4565b909150836000526020600020601f840160051c810160208510611f59575b90849392915b601f830160051c82018110611f4a575050611bcf565b60008155859450600101611f34565b5080611f2e565b60046040517f96bfb100000000000000000000000000000000000000000000000000000000008152fd5b6101017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000861617600055611b46565b60046040517f7ab84482000000000000000000000000000000000000000000000000000000008152fd5b50303b151580611b2a5750600160ff86161415611b2a565b5060ff85161515611b24565b346105f75760606003193601126105f757612029604435602435600435615d7e565b604080516001600160a01b03939093168352602083019190915290f35b346105f75760206003193601126105f75760043560005261016060205260606040600020546001600160a01b036040519163ffffffff80821684528160201c16602084015260401c166040820152f35b346105f75760206003193601126105f7576004356001600160a01b0381168091036105f7576120c433614c98565b8061215e575b6101cb9073ffffffffffffffffffffffffffffffffffffffff1982541617905560026040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f3391806113ef819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b6040516301ffc9a760e01b8152634058856760e11b6004820152602081602481855afa908115610b75576000916121c6575b506120ca57602490604051907f17ce95600000000000000000000000000000000000000000000000000000000082526004820152fd5b6121de915060203d8111610b6e57610b608183613f80565b82612190565b346105f75760206003193601126105f75760043560005261023160205260206001600160a01b0360406000205416604051908152f35b346105f75760006003193601126105f75760c06101c9546101ca54906101cb5490604051926001600160a01b0391828116855260a01c6020850152818116604085015260a01c60608401528116608083015260a01c60a0820152f35b346105f75760006003193601126105f75760206040516001600160a01b037f000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d0168152f35b346105f75760006003193601126105f75760206101c854604051908152f35b60806003193601126105f7576122ed613e88565b6024359060443560643567ffffffffffffffff81116105f7576123149036906004016140f3565b61231f9391936145c4565b6001600160a01b03809216936123358686614942565b34927f000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d09081166123a0575b506117449160009160405193849283927f6890e5b300000000000000000000000000000000000000000000000000000000845287898c3360048801614eff565b926123d56123ce867f0000000000000000000000000000000000000000000000000002c2ad68fd90006143e4565b8092614f31565b93600080808085856201adb0f16123ea6141fb565b50156123f65750612360565b6040517f4b789d360000000000000000000000000000000000000000000000000000000081526001600160a01b039190911660048201526024810191909152604490fd5b346105f75760206003193601126105f757610923612459600435614422565b6040519182918291909160808060a0830194805184526020810151602085015260408101516040850152606081015160608501520151910152565b346105f7576003196060813601126105f7576124ae613e88565b67ffffffffffffffff6024358181116105f7576124cf903690600401614121565b9390916044359081116105f7576124ea903690600401614121565b926001600160a01b039586861695338714158061272a575b6126e8575061251f929161251791369161402c565b93369161402c565b9383156126be578251918551830361112d576040519161253e83613f64565b600083526101cb54169182612625575b50505060005b8181106125a05750507f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb6125926000946040519182913395836142b9565b0390a4610486604051613f64565b6125aa8184614282565b51906125b68187614282565b5182600052609760208181526040600020886000528152604060002054918383106125fb57600195600052815260406000209088600052520360406000205501612554565b60046040517f5f896ec2000000000000000000000000000000000000000000000000000000008152fd5b823b156105f757869285600088612699829661267a9661268a6040519a8b998a988997634058856760e11b89523060048a01523360248a0152604489015288606489015260e0608489015260e4880190614095565b90848783030160a4880152614095565b918483030160c4850152613ed7565b03925af18015610b75576126af575b808061254e565b6126b890613f50565b846126a8565b60046040517f45d40ad5000000000000000000000000000000000000000000000000000000008152fd5b6040517f839c23f20000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03919091166024820152604490fd5b5086600052609860205260406000203360005260205260ff6040600020541615612502565b346105f75760206003193601126105f7576004356000526101c760205260206001600160a01b0360406000205416604051908152f35b346105f75760606003193601126105f75760043567ffffffffffffffff81116105f7576127b69036906004016140f3565b90604435906001600160a01b0382168092036105f7576020926127dc91610d03336148aa565b9081600052610231835260406000209073ffffffffffffffffffffffffffffffffffffffff198254161790556001606555604051908152f35b346105f75760406003193601126105f7576004356024356001600160a01b0381168091036105f7576128456145c4565b61284f8233614822565b8160005260209061012d825260406000208173ffffffffffffffffffffffffffffffffffffffff1982541617905580612919575b6040513382857f5010f780a0de79bcfb9f3d6fec3cfe29758ef5c5800d575af709bc590bd78ade600080a4836128e557507f56e810c8cae84731149f628981d25769a084570b9ba6eebf3c32879e3dce56099250604051908152a16001606555005b604091506000837f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b948352820152a2610f1a565b6040516301ffc9a760e01b81527f7bc7e6460000000000000000000000000000000000000000000000000000000060048201528281602481855afa908115610b7557600091612999575b5061288357602490604051907fda755beb0000000000000000000000000000000000000000000000000000000082526004820152fd5b6129b09150833d8511610b6e57610b608183613f80565b84612963565b346105f75760006003193601126105f7576020610945614f3e565b346105f7576129df366140c9565b6129eb83929333614d30565b60008281526101fe602081815260408084206001600160a01b039788168086529083529084208054951990951694859055909491939092839083907f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca9080a4159182612b4b575b82612b26575b5050612a6057005b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09160006040926101c99283549373ffffffffffffffffffffffffffffffffffffffff1985169055845193168352820152a160006040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f3391806113ef819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b9091506000805282526040600020906000528152600260406000205416158380612a58565b6101c954851682149250612a52565b346105f75760206003193601126105f757610923612459600435614483565b346105f75760006003193601126105f7576001600160a01b037f000000000000000000000000f62b0d56ba617f803df1c464c519ff7d29451b2f163003612be45760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b60046040517f5e4c25f1000000000000000000000000000000000000000000000000000000008152fd5b60406003193601126105f757612c22613e88565b60243567ffffffffffffffff81116105f757612c42903690600401613ff6565b906001600160a01b03807f000000000000000000000000f62b0d56ba617f803df1c464c519ff7d29451b2f1690813014612f0b577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc9080825416928303612ee1578392612cae33614c98565b6040517f21f743470000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201529316602484015260209283816044817f000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb8586165afa908115610b7557600091612ec4575b50156105f7577f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612d64575050506104869150614181565b8316906040517f52d1902d0000000000000000000000000000000000000000000000000000000081528381600481865afa60009181612e95575b50612dcd5760046040517fe5ec1769000000000000000000000000000000000000000000000000000000008152fd5b03612e6b57612ddb83614181565b604051907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a2835115801590612e63575b612e1557005b823b15612e3b575082600092839261048695519201905af4612e356141fb565b906143a3565b807f369891e70000000000000000000000000000000000000000000000000000000060049252fd5b506001612e0f565b60046040517f8373ebf0000000000000000000000000000000000000000000000000000000008152fd5b9091508481813d8311612ebd575b612ead8183613f80565b810103126105f757519087612d9e565b503d612ea3565b612edb9150843d8611610b6e57610b608183613f80565b86612d27565b60046040517f64cd8d19000000000000000000000000000000000000000000000000000000008152fd5b60046040517f1932df45000000000000000000000000000000000000000000000000000000008152fd5b346105f75760406003193601126105f75760043567ffffffffffffffff8082116105f757366023830112156105f757816004013590612f7382614014565b92612f816040519485613f80565b82845260209260248486019160051b830101913683116105f757602401905b82821061307c575050506024359081116105f757612fc290369060040161407a565b8251908051820361305257612fd682614014565b93612fe46040519586613f80565b828552601f19612ff384614014565b01368587013760005b838110613016576040518581528061092381880189614095565b806130416001600160a01b0361302e60019486614282565b511661303a8387614282565b519061422b565b61304b8289614282565b5201612ffc565b60046040517f4ce4cfdc000000000000000000000000000000000000000000000000000000008152fd5b81356001600160a01b03811681036105f7578152908401908401612fa0565b346105f75760406003193601126105f7576130b4613e9e565b6004356000526101fe6020526001600160a01b03604060002091166000526020526020604060002054604051908152f35b346105f75760206003193601126105f7576602c2ad68fd900060043581810291811591830414171561311c57602090604051908152f35b634e487b7160e01b600052601160045260246000fd5b346105f75760006003193601126105f7573360009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf650860205260409020546022161515801561320e575b156131e957476001600160a01b03906101ca91600080808085858854166204baf0f16131a86141fb565b50156131b057005b604492541690604051917fa489930c00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b6064604051634baa2a4d60e01b81523360048201526000602482015260206044820152fd5b503360009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020526040902054602216151561317e565b346105f7576020806003193601126105f757613262613e88565b6001600160a01b0391827f000000000000000000000000f62b0d56ba617f803df1c464c519ff7d29451b2f16803014612f0b577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc9084825416908103612ee157828461331a926132d133614c98565b6040517f21f743470000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201529116602482015291829081906044820190565b0381887f000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85165afa908115610b7557600091613485575b50156105f7576040519361336385613f64565b600085527f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561339e575050506104869150614181565b8316906040517f52d1902d0000000000000000000000000000000000000000000000000000000081528381600481865afa60009181613456575b506134075760046040517fe5ec1769000000000000000000000000000000000000000000000000000000008152fd5b03612e6b5761341583614181565b604051907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a283511580159061344e57612e1557005b506000612e0f565b9091508481813d831161347e575b61346e8183613f80565b810103126105f7575190876133d8565b503d613464565b61349c9150833d8511610b6e57610b608183613f80565b85613350565b346105f75760031960a0813601126105f7576134bc613e88565b906134c5613e9e565b9167ffffffffffffffff6044358181116105f7576134e790369060040161407a565b916064358281116105f75761350090369060040161407a565b916084359081116105f757613519903690600401613ff6565b6001600160a01b038092169533871415806137e8575b6105a8578451845181036130525783821693841561057e576101cb541680613756575b5060005b8181106136d557505082876040517f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb3391806135938a8c836142b9565b0390a43b61359d57005b6000602094613617613608976135f894604051998a98899788967fbc197c81000000000000000000000000000000000000000000000000000000009e8f89523360048a0152602489015260a0604489015260a4880190614095565b9084878303016064880152614095565b91848303016084850152613ed7565b03925af1600091816136b5575b5061367d5750506001613635614316565b6308c379a014613646575b61048857005b61364e614334565b806136595750613640565b6104e79060405191829162461bcd60e51b8352602060048401526024830190613ed7565b7fffffffff000000000000000000000000000000000000000000000000000000001614610486576004604051633fbfe7f560e21b8152fd5b6136ce91925060203d811161054d5761053e8183613f80565b9083613624565b6136df8188614282565b51906136eb8188614282565b518260005260206097815260406000208c60005281526040600020549082821061055457846001956000526097825260406000208a600052825260406000206137358582546142ac565b9055600052609781526040600020908d600052520360406000205501613556565b803b156105f7576000876137aa9287838d6137ca8e6137ba8e6040519a8b998a988997634058856760e11b89523060048a01523360248a01526044890152606488015260e0608488015260e4870190614095565b90838683030160a4870152614095565b908382030160c48401528b613ed7565b03925af18015610b755715613552576137e290613f50565b88613552565b5086600052609860205260406000203360005260205260ff604060002054161561352f565b346105f75760406003193601126105f757613829600435615cff565b6001600160a01b03604061387361384c60243563ffffffff6020870151166143e4565b7f00000000000000000000000000000000000000000000000000000000000027109061578f565b9201511661092360405192839283602090939291936001600160a01b0360408201951681520152565b346105f75760606003193601126105f7576138b5613e88565b6024356000526101fe6020526001600160a01b03604060002091166000526020526020604435600217604060002054161515604051908152f35b346105f75760406003193601126105f75767ffffffffffffffff6004356024358281116105f757613924903690600401613ff6565b9161392f8233614822565b81156105f75760405191807f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b6020948581528061396e87820189613ed7565b0390a26000526101c68252604060002091835191821161083d5761399283546144e3565b601f8111613a3a575b5080601f83116001146139d757508192936000926139cc575b50506000198260011b9260031b1c1916179055600080f35b0151905083806139b4565b90601f198316948460005282600020926000905b878210613a22575050836001959610613a09575b505050811b019055005b015160001960f88460031b161c191690558380806139ff565b806001859682949686015181550195019301906139eb565b8360005281600020601f840160051c810191838510613a76575b601f0160051c01905b818110613a6a575061399b565b60008155600101613a5d565b9091508190613a54565b346105f75760006003193601126105f757602060405160088152f35b346105f75760406003193601126105f757600435613ab8613e9e565b9080600052610231806020526001600160a01b039182604060002054163303613b09576000526020526040600020911673ffffffffffffffffffffffffffffffffffffffff19825416179055600080f35b60046040517f2afb0ecf000000000000000000000000000000000000000000000000000000008152fd5b346105f75760206003193601126105f757613b4c613e88565b613b5533614c98565b6001600160a01b03811660009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf6508602052604090205460021615613b9e5761048690615aed565b60046040517f98ee9d38000000000000000000000000000000000000000000000000000000008152fd5b346105f75760006003193601126105f75760206040517f0000000000000000000000000000000000000000000000000002c2ad68fd90008152f35b346105f75760206003193601126105f757610486613c1f613e88565b613c2833614764565b615bc8565b346105f75760206003193601126105f75761092361090f600435615a62565b346105f75760006003193601126105f75760405160006101938054613c70816144e3565b80855291600191808316908115613cf65750600114613c9a575b6109238561090f81870382613f80565b600090815292507ffc8af01f449989052b52093a58fc9f42d0b11f0c6dd5dca0463dab62346ccc685b828410613cde57505050810160200161090f82610923613c8a565b80546020858701810191909152909301928101613cc3565b8695506109239693506020925061090f94915060ff191682840152151560051b8201019293613c8a565b346105f75760206003193601126105f7576004357fffffffff0000000000000000000000000000000000000000000000000000000081168091036105f757807f2a55205a0000000000000000000000000000000000000000000000000000000060209214908115613e13575b8115613d9e575b506040519015158152f35b7fd9b67a2600000000000000000000000000000000000000000000000000000000811491508115613de9575b8115613dd8575b5082613d93565b6301ffc9a760e01b91501482613dd1565b7f0e89341c0000000000000000000000000000000000000000000000000000000081149150613dca565b7f2920ca160000000000000000000000000000000000000000000000000000000081149150613d8c565b346105f75760006003193601126105f757602060405160008152f35b346105f75760406003193601126105f7576020613e80613e77613e88565b6024359061422b565b604051908152f35b600435906001600160a01b03821682036105f757565b602435906001600160a01b03821682036105f757565b60005b838110613ec75750506000910152565b8181015183820152602001613eb7565b90601f19601f602093613ef581518092818752878088019101613eb4565b0116010190565b6060810190811067ffffffffffffffff82111761083d57604052565b60a0810190811067ffffffffffffffff82111761083d57604052565b6040810190811067ffffffffffffffff82111761083d57604052565b67ffffffffffffffff811161083d57604052565b6020810190811067ffffffffffffffff82111761083d57604052565b90601f601f19910116810190811067ffffffffffffffff82111761083d57604052565b67ffffffffffffffff811161083d57601f01601f191660200190565b929192613fcb82613fa3565b91613fd96040519384613f80565b8294818452818301116105f7578281602093846000960137010152565b9080601f830112156105f75781602061401193359101613fbf565b90565b67ffffffffffffffff811161083d5760051b60200190565b929161403782614014565b916140456040519384613f80565b829481845260208094019160051b81019283116105f757905b82821061406b5750505050565b8135815290830190830161405e565b9080601f830112156105f7578160206140119335910161402c565b90815180825260208080930193019160005b8281106140b5575050505090565b8351855293810193928101926001016140a7565b60031960609101126105f757600435906024356001600160a01b03811681036105f7579060443590565b9181601f840112156105f75782359167ffffffffffffffff83116105f757602083818601950101116105f757565b9181601f840112156105f75782359167ffffffffffffffff83116105f7576020808501948460051b0101116105f757565b602081526060604061416f84518360208601526080850190613ed7565b93602081015182850152015191015290565b803b156141d1576001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc911673ffffffffffffffffffffffffffffffffffffffff19825416179055565b60046040517f529880eb000000000000000000000000000000000000000000000000000000008152fd5b3d15614226573d9061420c82613fa3565b9161421a6040519384613f80565b82523d6000602084013e565b606090565b6001600160a01b031690811561425857600052609760205260406000209060005260205260406000205490565b60046040517f8620cc34000000000000000000000000000000000000000000000000000000008152fd5b80518210156142965760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b9190820180921161311c57565b90916142d061401193604084526040840190614095565b916020818403910152614095565b908160209103126105f757517fffffffff00000000000000000000000000000000000000000000000000000000811681036105f75790565b60009060033d1161432357565b905060046000803e60005160e01c90565b600060443d106140115760405160031991823d016004833e815167ffffffffffffffff918282113d6024840111176143925781840194855193841161439a573d85010160208487010111614392575061401192910160200190613f80565b949350505050565b50949350505050565b156143ab5790565b8051156143ba57805190602001fd5b60046040517fa1451936000000000000000000000000000000000000000000000000000000008152fd5b8181029291811591840414171561311c57565b6040519061440482613f18565b60006080838281528260208201528260408201528260608201520152565b61442a6143f7565b5066012edc9ab5d00090818102918115908284041481171561311c576564f43391f00080830292830414171561311c576040519161446783613f18565b8252806020830152806040830152806060830152608082015290565b61448b6143f7565b5065c9e86723e000808202908215908383041481171561311c576564f43391f00080840293840414171561311c57604051916144c683613f18565b600083528160208401528160408401526060830152608082015290565b90600182811c92168015614513575b60208310146144fd57565b634e487b7160e01b600052602260045260246000fd5b91607f16916144f2565b9060405191826000825492614531846144e3565b9081845260019485811690816000146145a0575060011461455d575b505061455b92500383613f80565b565b9093915060005260209081600020936000915b81831061458857505061455b9350820101388061454d565b85548884018501529485019487945091830191614570565b905061455b95506020935060ff1991501682840152151560051b820101388061454d565b6002606554146145d5576002606555565b606460405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b90815167ffffffffffffffff811161083d576101939061463982546144e3565b601f81116146ff575b50602080601f831160011461467e575081929394600092614673575b50506000198260011b9260031b1c1916179055565b01519050388061465e565b90601f19831695846000527ffc8af01f449989052b52093a58fc9f42d0b11f0c6dd5dca0463dab62346ccc68926000905b8882106146e7575050836001959697106146ce575b505050811b019055565b015160001960f88460031b161c191690553880806146c4565b806001859682949686015181550195019301906146af565b60008381527ffc8af01f449989052b52093a58fc9f42d0b11f0c6dd5dca0463dab62346ccc68601f840160051c8101926020851061475a575b601f0160051c01915b82811061474f575050614642565b818155600101614741565b9092508290614738565b6001600160a01b03811660009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020526040902054602216151580156147df575b156147b05750565b6064906001600160a01b0360405191634baa2a4d60e01b83521660048201526000602482015260206044820152fd5b506001600160a01b03811660009081527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf6508602052604090205460221615156147a8565b9060008181526101fe90816020526001600160a01b036040822094169384825260205260126040822054161591821592614887575b505015614862575050565b6064925060405191634baa2a4d60e01b83526004830152602482015260106044820152fd5b601292509060409181805260205281812085825260205220541615153880614857565b6001600160a01b031660008181527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020526040812054600616158015906101fe90614920575b50156148fb575050565b6064925060405191634baa2a4d60e01b83526004830152602482015260046044820152fd5b90508180526020526040812082825260205260066040822054161515386148f1565b9060008181526101fe90816020526001600160a01b036040822094169384825260205260066040822054161591821592614982575b5050156148fb575050565b600692509060409181805260205281812085825260205220541615153880614977565b601f8260209493601f19938186528686013760008582860101520116010190565b93929091936149d6368483613fbf565b906101c893845494600186019055604051926149f184613efc565b835286602084015260006040840152846000526101c6602052604060002096835197885167ffffffffffffffff811161083d57614a2e82546144e3565b99601f8b11614c54575b88999a5060009896979850602090601f8311600114614bbf579180889993927f1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc068999593600092614bb4575b50506000198260011b9260031b1c19161781555b60208201516001820155600260408301519101557f5086d1bcea28999da9875111e3592688fbfa821db63214c695ca35768080c2fe60405180614adb339482614152565b0390a3846000526101fe806020526001600160a01b0360406000209716968760005260205260026040600020541790866000526020526040600020876000526020528060406000205586867f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca600080a481614b74575b614b686040519384936040855260408501916149a5565b9060208301520390a390565b847f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b6040516020815280614bac6020820187896149a5565b0390a2614b51565b015190503880614a83565b979291908260005260206000209860005b601f1984168110614c3957509188996001927f1b944478023872bf91b25a13fdba3a686fdb1bf4dbb872f850240fad4b8cc0689a96959483601f19811610614c20575b505050811b018155614a97565b015160001960f88460031b161c19169055388080614c13565b828201518b556001909a01998c995060209283019201614bd0565b826000526020600020601f830160051c810160208410614c91575b601f8d0160051c82018110614c85575050614a38565b60008155600101614c6f565b5080614c6f565b6001600160a01b031660008181527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020526040812054600216158015906101fe90614d0e575b5015614ce9575050565b6064925060405191634baa2a4d60e01b83526004830152602482015260026044820152fd5b9050818052602052604081208282526020526002604082205416151538614cdf565b9060008181526101fe90816020526001600160a01b036040822094169384825260205260026040822054161591821592614d70575b505015614ce9575050565b600292509060409181805260205281812085825260205220541615153880614d65565b600019811461311c5760010190565b90929192614daf81613fa3565b91614dbd6040519384613f80565b8294828452828201116105f757602061455b930190613eb4565b60209081818403126105f757805167ffffffffffffffff918282116105f757019060409081838603126105f757815194614e1086613f34565b83518281116105f75784019181601f840112156105f757825190614e3382614014565b94614e4081519687613f80565b828652878087019360051b860101948486116105f757908189809998979695949301935b868510614e7d5750505050505050845201519082015290565b9091929380959697989950518481116105f75782019083601f1983890301126105f757835191614eac83613f34565b8b81015160038110156105f757835284810151908682116105f757019087603f830112156105f7578b92614ee889848887809701519101614da2565b838201528152019401929190899897969594614e64565b919260a0936001600160a01b0361401198969316845260208401526040830152606082015281608082015201916149a5565b9190820391821161311c57565b6101ca546001600160a01b03168015614f545790565b503090565b909194939460009283946602c2ad68fd9000938483029483860414831517156152c05784811015614fae5760046040517fede1d8dc000000000000000000000000000000000000000000000000000000008152fd5b80850361513657508093614fc28993614422565b986001600160a01b038093161561510e575b8216156150e6575b817f0000000000000000000000007777777f279eba3d3ad8f4e708545291a6fdba8b16928951948a6020810151926080606060408401519301519d015193873b156150e25791868094928c9d9e9f948260409e9d9e519e8f9d8e9c8d987ffaa3516f000000000000000000000000000000000000000000000000000000008a521660048199015260248d01521660448b015260648a015216608488015260a487015260c486015260e48501527f000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d0166101048401526101248301525a9261014493f180156150d7576150cc57505090565b614011919250613f50565b6040513d84823e3d90fd5b8a80fd5b7f000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d09250614fdc565b7f000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d09550614fd4565b955091908297949396979261514b8692614483565b906001600160a01b03968780921615615298575b1615615270575b857f0000000000000000000000007777777f279eba3d3ad8f4e708545291a6fdba8b16926020820151926040830151906080606085015194015194863b1561526c57928897969594928a80959381946040519d8e9b7ffaa3516f000000000000000000000000000000000000000000000000000000008d528d8d816004820152602401521660448c015260648b015216608489015260a48801521660c486015260e48501527f000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d01661010484015261012483015281875a9261014493f1908115615260575061525357500390565b61525c90613f50565b0390565b604051903d90823e3d90fd5b8880fd5b7f000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d09150615166565b7f000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d0955061515f565b602486634e487b7160e01b81526011600452fd5b600311156152de57565b634e487b7160e01b600052602160045260246000fd5b51906001600160a01b03821682036105f757565b929160005b84518110156154b4576153208186614282565b515161532b816152d4565b615334816152d4565b600181036153f7575060208061534a8388614282565b51015160409182828051810103126105f757615368839183016152f4565b910151908186116153ce5760008080936001600160a01b038294166204baf0f16153906141fb565b50156153a557506153a090614d93565b61530d565b600490517fe373ab5c000000000000000000000000000000000000000000000000000000008152fd5b600483517f644f3cdc000000000000000000000000000000000000000000000000000000008152fd5b806154036002926152d4565b036154ab576020806154158388614282565b51015160609182828051810103126105f7576154329082016152f4565b9160409081830151920151918580151591826154a0575b50506154775791610e0391856001600160a01b036153a09695519361546d85613f64565b60008552166154d3565b600490517f4cdcfbf9000000000000000000000000000000000000000000000000000000008152fd5b141590508538615449565b6153a090614d93565b5050509050565b908160209103126105f7575180151581036105f75790565b9092916155036155089382866154ea838383615799565b956154fe6154f888856142ac565b836156fb565b615529565b6142ac565b906000526101c660205261552560026040600020019182546142ac565b9055565b9291906001600160a01b0384168015611157576000928284526020946097865260409687862084875287528786206155628482546142ac565b905583868951878152858a8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628b3392a43b6155a4575b50505050505050565b6155ff9286928689518096819582947ff23a6e61000000000000000000000000000000000000000000000000000000009a8b85523360048601528560248601526044850152606484015260a0608484015260a4830190613ed7565b03925af18391816156dc575b5061569b57505060019161561d614316565b6308c379a014615665575b505061563c57505b3880808080808061559b565b600490517fefab6922000000000000000000000000000000000000000000000000000000008152fd5b61566d614334565b91826156795750615628565b846104e791505192839262461bcd60e51b845260048401526024830190613ed7565b7fffffffff00000000000000000000000000000000000000000000000000000000160391506156cc90505750615630565b60049051633fbfe7f560e21b8152fd5b6156f4919250853d871161054d5761053e8183613f80565b903861560b565b90816000526101c6602052604060002090600282015490600161571e82846142ac565b93015480931161572e5750505050565b60849450604051937f1255c8fd0000000000000000000000000000000000000000000000000000000085526004850152602484015260448301526064820152fd5b8115615779570690565b634e487b7160e01b600052601260045260246000fd5b8115615779570490565b92919092600093818552610160948560205263ffffffff916040928084842054169081156158a0575b508015615896578483526101c6602052600184842001549060028585200154906157f56157ef828461576f565b856142ac565b60001982019182116152c057916158136158199261581f959461578f565b946142ac565b90614f31565b8082101561588e5750955b86615837575b5050505050565b8382526020526001600160a01b038083832054841c1692831561587b575b50821615615874575061586a92918591615529565b3880808080615830565b9450505050565b82805280832054901c8116925038615855565b90509561582a565b5090955050505050565b90508280528383205416386157c2565b6020818303126105f75780519067ffffffffffffffff82116105f757019080601f830112156105f757815161401192602001614da2565b6000805261012d6020527fa581b17bfc4d6578e300cafbf34fd2dc1fef0270d8c73f88a99dcde2859a6639546001600160a01b039081168015615992575b168061593457506140116159a0565b6000600491604051928380927fe8a3d4850000000000000000000000000000000000000000000000000000000082525afa908115610b7557600091615977575090565b614011913d8091833e61598a8183613f80565b8101906158b0565b508060406000205416615925565b60008080526101c690816020526040916159bc838320546144e3565b615a52575080805261012d6020526001600160a01b0390808284822054168015615a46575b60248551809581937f0e89341c000000000000000000000000000000000000000000000000000000008352856004840152165afa928315615a3c57508092615a2857505090565b61401192503d8091833e61598a8183613f80565b51903d90823e3d90fd5b508284822054166159e1565b818052602052206140119061451d565b6000908082526101c680602052615a7c60408420546144e3565b615ada5750816001600160a01b03615a9383615ccc565b16916024604051809481937f0e89341c00000000000000000000000000000000000000000000000000000000835260048301525afa918215615260578092615a2857505090565b916140119260409282526020522061451d565b6101c980546001600160a01b0392831673ffffffffffffffffffffffffffffffffffffffff19821681179092556040805193909116835260208301919091527f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a160006040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f339180615bc3819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b0390a3565b6001600160a01b036101ca911673ffffffffffffffffffffffffffffffffffffffff1982541617905560016040517f3be6d3a1d957610f7e900c66889b874cdc9f0c22901aa8be6ec3d2d04c14ca0f339180615bc3819060c082019160a06101c9546001600160a01b03908181168452821c60208401526101ca548181166040850152821c60608401526101cb549081166080840152811c910152565b6001600160a01b031660008181527f5f4301e3e862ad13c0503d3de32ba4e2e40c90733d1da23c9df4d0addbcf65086020526040812080546002179081905591907f35fb03d0d293ef5b362761900725ce891f8f766b5a662cdd445372355448e7ca8180a4565b60005261012d6020526001600160a01b03908160406000205416918215615cf05750565b60008080526040902054169150565b6040805191615d0d83613efc565b600090818452818360209582878201520152815281610160918285526001600160a01b03928383832054841c16615d6f5781805285522092825193615d5185613efc565b549063ffffffff808316865282821c1690850152821c169082015290565b502092825193615d5185613efc565b615d8a90939293615cff565b9263ffffffff9182855116908115615ddf57615db09291615daa9161576f565b906142ac565b90600019818551160181811161311c576001600160a01b0392604092615dd792169061578f565b930151169190565b505050509060406001600160a01b039101511690600090565b9190615e0381614014565b90604091615e1383519182613f80565b818152601f19615e2283614014565b0160005b818110615f3e575050809460005b838110615e42575050505050565b8060051b8201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1833603018112156105f75782019081359167ffffffffffffffff83116105f75760208091019083360382136105f757600080615eae615f1e94615f39973691613fbf565b8a5193615eba85613efc565b602785527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c818601527f206661696c6564000000000000000000000000000000000000000000000000008c86015281519101305af4615f176141fb565b9030615f4f565b615f288286614282565b52615f338185614282565b50614d93565b615e34565b806060602080938601015201615e26565b91929015615fb05750815115615f63575090565b3b15615f6c5790565b606460405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156136595750805190602001fdfea26469706673582212209d661661ec61b1198babb33ada415cf81d60c9ed199bd8d15eac67510139096b64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000002c2ad68fd9000000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d0000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb850000000000000000000000007777777f279eba3d3ad8f4e708545291a6fdba8b
-----Decoded View---------------
Arg [0] : _mintFeeAmount (uint256): 777000000000000
Arg [1] : _mintFeeRecipient (address): 0xd1d1D4e36117aB794ec5d4c78cBD3a8904E691D0
Arg [2] : _factory (address): 0xA6C5f2DE915240270DaC655152C3f6A91748cb85
Arg [3] : _protocolRewards (address): 0x7777777F279eba3d3Ad8F4E708545291A6fDBA8B
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000002c2ad68fd9000
Arg [1] : 000000000000000000000000d1d1d4e36117ab794ec5d4c78cbd3a8904e691d0
Arg [2] : 000000000000000000000000a6c5f2de915240270dac655152c3f6a91748cb85
Arg [3] : 0000000000000000000000007777777f279eba3d3ad8f4e708545291a6fdba8b
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.