APE Price: $1.14 (+7.17%)

Contract

0x6dC5807302D49edf196114643350E75Ca345022f

Overview

APE Balance

Apechain LogoApechain LogoApechain Logo0 APE

APE Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0x60a0806016550002024-10-25 4:01:572 days ago1729828917IN
 Create: CreatorRedeemMinterFactory
0 APE0.0511236725.42069

Latest 1 internal transaction

Parent Transaction Hash Block From To
16550002024-10-25 4:01:572 days ago1729828917
0x6dC58073...Ca345022f
 Contract Creation0 APE

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CreatorRedeemMinterFactory

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 31 : CreatorRedeemMinterFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol";
import { IERC165 } from "@openzeppelin/contracts/interfaces/IERC165.sol";

import { IContractMetadata } from "../../interfaces/IContractMetadata.sol";
import { IVersionedContract } from "../../interfaces/IVersionedContract.sol";
import { IMinter1155 } from "../../interfaces/IMinter1155.sol";
import { ICreatorCommands } from "../../interfaces/ICreatorCommands.sol";
import { CreatorRedeemMinterStrategy } from "./CreatorRedeemMinterStrategy.sol";
import { ICreator1155 } from "../../interfaces/ICreator1155.sol";
import { SharedBaseConstants } from "../../shared/SharedBaseConstants.sol";

/// @title CreatorRedeemMinterFactory
/// @notice A factory for CreatorRedeemMinterStrategy contracts
contract CreatorRedeemMinterFactory is IContractMetadata, SharedBaseConstants, IVersionedContract, IMinter1155 {
    bytes4 constant LEGACY_IMINTER1155_INTERFACE_ID = 0x6467a6fc;
    address public immutable redeemMinterImplementation;

    event RedeemMinterDeployed(address indexed creatorContract, address indexed minterContract);

    error CallerNotCreator1155();
    error MinterContractAlreadyExists();
    error MinterContractDoesNotExist();

    constructor() {
        redeemMinterImplementation = address(new CreatorRedeemMinterStrategy());
    }

    /// @notice Factory contract name
    function contractName() external pure override returns (string memory) {
        return "Redeem Minter Factory";
    }

    /// @notice Factory contract version
    function contractVersion() external pure override returns (string memory) {
        return "1";
    }

    /// @notice No-op function for IMinter1155 compatibility
    function requestMint(
        address sender,
        uint256 tokenId,
        uint256 quantity,
        uint256 ethValueSent,
        bytes calldata minterArguments
    )
        external
        returns (ICreatorCommands.CommandSet memory commands)
    { }

    /// @notice IERC165 interface support
    function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {
        return interfaceId == type(IMinter1155).interfaceId || interfaceId == type(IERC165).interfaceId;
    }

    /// @notice Deploys a new CreatorRedeemMinterStrategy for caller Creator1155 contract if none exists
    function createMinterIfNoneExists() external {
        if (!IERC165(msg.sender).supportsInterface(type(ICreator1155).interfaceId)) {
            revert CallerNotCreator1155();
        }
        if (doesRedeemMinterExistForCreatorContract(msg.sender)) {
            return;
        }
        address minter = Clones.cloneDeterministic(redeemMinterImplementation, keccak256(abi.encode(msg.sender)));
        CreatorRedeemMinterStrategy(minter).initialize(msg.sender);

        emit RedeemMinterDeployed(msg.sender, minter);
    }

    /// @notice Returns deterministic address of a CreatorRedeemMinterStrategy for a given Creator1155 contract
    /// @param _creatorContract Creator1155 contract address
    /// @return Address of CreatorRedeemMinterStrategy
    function predictMinterAddress(address _creatorContract) public view returns (address) {
        return Clones.predictDeterministicAddress(
            redeemMinterImplementation, keccak256(abi.encode(_creatorContract)), address(this)
        );
    }

    /// @notice Returns true if a CreatorRedeemMinterStrategy has been deployed for a given Creator1155 contract
    /// @param _creatorContract Creator1155 contract address
    /// @return True if a CreatorRedeemMinterStrategy has been deployed for a given Creator1155 contract
    function doesRedeemMinterExistForCreatorContract(address _creatorContract) public view returns (bool) {
        return predictMinterAddress(_creatorContract).code.length > 0;
    }

    /// @notice Returns address of deployed CreatorRedeemMinterStrategy for a given Creator1155 contract
    /// @param _creatorContract Creator1155 contract address
    /// @return Address of deployed CreatorRedeemMinterStrategy
    function getDeployedRedeemMinterForCreatorContract(address _creatorContract) external view returns (address) {
        address minter = predictMinterAddress(_creatorContract);
        if (minter.code.length == 0) {
            revert MinterContractDoesNotExist();
        }
        return minter;
    }
}

File 2 of 31 : Clones.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/Clones.sol)

pragma solidity ^0.8.0;

/**
 * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for
 * deploying minimal proxy contracts, also known as "clones".
 *
 * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
 * > a minimal bytecode implementation that delegates all calls to a known, fixed address.
 *
 * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
 * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
 * deterministic method.
 *
 * _Available since v3.4._
 */
library Clones {
    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create opcode, which should never revert.
     */
    function clone(address implementation) internal returns (address instance) {
        /// @solidity memory-safe-assembly
        assembly {
            // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
            // of the `implementation` address with the bytecode before the address.
            mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
            // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
            mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
            instance := create(0, 0x09, 0x37)
        }
        require(instance != address(0), "ERC1167: create failed");
    }

    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create2 opcode and a `salt` to deterministically deploy
     * the clone. Using the same `implementation` and `salt` multiple time will revert, since
     * the clones cannot be deployed twice at the same address.
     */
    function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
        /// @solidity memory-safe-assembly
        assembly {
            // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
            // of the `implementation` address with the bytecode before the address.
            mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
            // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
            mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
            instance := create2(0, 0x09, 0x37, salt)
        }
        require(instance != address(0), "ERC1167: create2 failed");
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(add(ptr, 0x38), deployer)
            mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)
            mstore(add(ptr, 0x14), implementation)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)
            mstore(add(ptr, 0x58), salt)
            mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))
            predicted := keccak256(add(ptr, 0x43), 0x55)
        }
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(
        address implementation,
        bytes32 salt
    ) internal view returns (address predicted) {
        return predictDeterministicAddress(implementation, salt, address(this));
    }
}

File 3 of 31 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol)

pragma solidity ^0.8.0;

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

File 4 of 31 : IContractMetadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

interface IContractMetadata {
    /// @notice Contract name returns the pretty contract name
    function contractName() external returns (string memory);
}

File 5 of 31 : IVersionedContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

interface IVersionedContract {
    function contractVersion() external returns (string memory);
}

File 6 of 31 : IMinter1155.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import { IERC165Upgradeable } from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
import { ICreatorCommands } from "./ICreatorCommands.sol";

/// @notice Minter standard interface
/// @dev Minters need to confirm to the ERC165 selector of type(IMinter1155).interfaceId
interface IMinter1155 is IERC165Upgradeable {
    function requestMint(
        address sender,
        uint256 tokenId,
        uint256 quantity,
        uint256 ethValueSent,
        bytes calldata minterArguments
    )
        external
        returns (ICreatorCommands.CommandSet memory commands);
}

File 7 of 31 : ICreatorCommands.sol
// 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;
    }
}

File 8 of 31 : CreatorRedeemMinterStrategy.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import { IERC1155 } from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import { ICreatorCommands } from "../../interfaces/ICreatorCommands.sol";
import { SaleStrategy } from "../SaleStrategy.sol";
import { SaleCommandHelper } from "../utils/SaleCommandHelper.sol";

/// @title CreatorRedeemMinterStrategy
/// @notice A strategy that allows minting by redeeming other (ERC20/721/1155) tokens
contract CreatorRedeemMinterStrategy is SaleStrategy, Initializable {
    using SaleCommandHelper for ICreatorCommands.CommandSet;
    using SafeERC20 for IERC20;

    enum TokenType {
        NULL,
        ERC721,
        ERC1155,
        ERC20
    }

    struct MintToken {
        /// @notice The address of the minting token contract (always creatorContract)
        address tokenContract;
        /// @notice The mint tokenId
        uint256 tokenId;
        /// @notice The amount of tokens that can be minted
        uint256 amount;
        /// @notice The mint token type (alwas ERC1155)
        TokenType tokenType;
    }

    struct RedeemInstruction {
        /// @notice The type of token to be redeemed
        TokenType tokenType;
        /// @notice The amount of tokens to be redeemed
        uint256 amount;
        /// @notice The start of the range of token ids to be redeemed
        uint256 tokenIdStart;
        /// @notice The end of the range of token ids to be redeemed
        uint256 tokenIdEnd;
        /// @notice The address of the token contract to be redeemed
        address tokenContract;
        /// @notice The address to transfer the redeemed tokens to
        address transferRecipient;
        /// @notice The function to call on the token contract to burn the tokens
        bytes4 burnFunction;
    }

    struct RedeemInstructions {
        /// @notice The token to be minted
        MintToken mintToken;
        /// @notice The instructions for redeeming tokens
        RedeemInstruction[] instructions;
        /// @notice The start of the sale
        uint64 saleStart;
        /// @notice The end of the sale
        uint64 saleEnd;
        /// @notice The amount of ETH to send to the recipient
        uint256 ethAmount;
        /// @notice The address to send the ETH to (0x0 for the creator contract)
        address ethRecipient;
    }

    event RedeemSet(address indexed target, bytes32 indexed redeemsInstructionsHash, RedeemInstructions data);
    event RedeemProcessed(
        address indexed target,
        bytes32 indexed redeemsInstructionsHash,
        address sender,
        uint256[][] tokenIds,
        uint256[][] amounts
    );
    event RedeemsCleared(address indexed target, bytes32[] indexed redeemInstructionsHashes);

    error RedeemInstructionAlreadySet();
    error RedeemInstructionNotAllowed();
    error IncorrectNumberOfTokenIds();
    error InvalidTokenIdsForTokenType();
    error InvalidSaleEndOrStart();
    error EmptyRedeemInstructions();
    error MintTokenTypeMustBeERC1155();
    error MustBurnOrTransfer();
    error IncorrectMintAmount();
    error IncorrectBurnOrTransferAmount();
    error InvalidCreatorContract();
    error SaleEnded();
    error SaleHasNotStarted();
    error InvalidTokenType();
    error WrongValueSent();
    error CallerNotCreatorContract();
    error BurnFailed();
    error MustCallClearRedeem();
    error TokenIdOutOfRange();
    error MintTokenContractMustBeCreatorContract();
    error SenderIsNotTokenOwner();

    /// @notice tokenId, keccak256(abi.encode(RedeemInstructions)) => redeem instructions are allowed
    mapping(uint256 => mapping(bytes32 => bool)) public redeemInstructionsHashIsAllowed;

    /// @notice creator contract
    address public creatorContract;

    modifier onlyCreatorContract() {
        if (msg.sender != creatorContract) {
            revert CallerNotCreatorContract();
        }
        _;
    }

    function initialize(address _creatorContract) public initializer {
        if (_creatorContract == address(0)) {
            revert InvalidCreatorContract();
        }
        creatorContract = _creatorContract;
    }

    /// @notice Redeem Minter Strategy contract name
    function contractName() external pure override returns (string memory) {
        return "Redeem Minter Sale Strategy";
    }

    /// @notice Redeem Minter Strategy contract version
    function contractVersion() external pure override returns (string memory) {
        return "1";
    }

    /// @notice Redeem instructions object hash
    /// @param _redeemInstructions The redeem instructions object
    function redeemInstructionsHash(RedeemInstructions memory _redeemInstructions) public pure returns (bytes32) {
        return keccak256(abi.encode(_redeemInstructions));
    }

    function validateSingleRedeemInstruction(RedeemInstruction calldata _redeemInstruction) internal pure {
        if (_redeemInstruction.tokenType == TokenType.ERC20) {
            if (_redeemInstruction.tokenIdStart != 0 || _redeemInstruction.tokenIdEnd != 0) {
                revert InvalidTokenIdsForTokenType();
            }
        } else if (
            _redeemInstruction.tokenType == TokenType.ERC721 || _redeemInstruction.tokenType == TokenType.ERC1155
        ) {
            if (_redeemInstruction.tokenIdStart > _redeemInstruction.tokenIdEnd) {
                revert InvalidTokenIdsForTokenType();
            }
        } else {
            revert InvalidTokenType();
        }
        if (_redeemInstruction.burnFunction != 0 && _redeemInstruction.transferRecipient != address(0)) {
            revert MustBurnOrTransfer();
        }
        if (_redeemInstruction.burnFunction == 0 && _redeemInstruction.transferRecipient == address(0)) {
            revert MustBurnOrTransfer();
        }
        if (_redeemInstruction.amount == 0) {
            revert IncorrectMintAmount();
        }
    }

    /// @notice Validate redeem instructions
    /// @param _redeemInstructions The redeem instructions object
    function validateRedeemInstructions(RedeemInstructions calldata _redeemInstructions) public view {
        if (
            _redeemInstructions.saleEnd <= _redeemInstructions.saleStart
                || _redeemInstructions.saleEnd <= block.timestamp
        ) {
            revert InvalidSaleEndOrStart();
        }
        if (_redeemInstructions.instructions.length == 0) {
            revert EmptyRedeemInstructions();
        }
        if (_redeemInstructions.mintToken.tokenContract != creatorContract) {
            revert MintTokenContractMustBeCreatorContract();
        }
        if (_redeemInstructions.mintToken.tokenType != TokenType.ERC1155) {
            revert MintTokenTypeMustBeERC1155();
        }

        uint256 numInstructions = _redeemInstructions.instructions.length;

        unchecked {
            for (uint256 i; i < numInstructions; ++i) {
                validateSingleRedeemInstruction(_redeemInstructions.instructions[i]);
            }
        }
    }

    /// @notice Set redeem instructions
    /// @param tokenId The token id to set redeem instructions for
    /// @param _redeemInstructions The redeem instructions object
    function setRedeem(uint256 tokenId, RedeemInstructions calldata _redeemInstructions) external onlyCreatorContract {
        if (_redeemInstructions.mintToken.tokenId != tokenId) {
            revert InvalidTokenIdsForTokenType();
        }

        validateRedeemInstructions(_redeemInstructions);

        bytes32 hash = redeemInstructionsHash(_redeemInstructions);
        if (redeemInstructionsHashIsAllowed[tokenId][hash]) {
            revert RedeemInstructionAlreadySet();
        }
        redeemInstructionsHashIsAllowed[tokenId][hash] = true;

        emit RedeemSet(creatorContract, hash, _redeemInstructions);
    }

    /// @notice Clear redeem instructions
    /// @param tokenId The token id to clear redeem instructions for
    /// @param hashes Array of redeem instructions hashes to clear
    function clearRedeem(uint256 tokenId, bytes32[] calldata hashes) external onlyCreatorContract {
        uint256 numHashes = hashes.length;

        unchecked {
            for (uint256 i; i < numHashes; ++i) {
                redeemInstructionsHashIsAllowed[tokenId][hashes[i]] = false;
            }
        }

        emit RedeemsCleared(creatorContract, hashes);
    }

    /// @notice Request mint
    /// @param tokenId The token id to mint
    /// @param amount The amount to mint
    /// @param ethValueSent The amount of eth sent
    /// @param minterArguments The abi encoded minter arguments (address, RedeemInstructions, uint256[][], uint256[][])
    function requestMint(
        address sender,
        uint256 tokenId,
        uint256 amount,
        uint256 ethValueSent,
        bytes calldata minterArguments
    )
        external
        onlyCreatorContract
        returns (ICreatorCommands.CommandSet memory commands)
    {
        (RedeemInstructions memory redeemInstructions, uint256[][] memory tokenIds, uint256[][] memory amounts) = abi.decode(
            minterArguments,
            (RedeemInstructions, uint256[][], uint256[][])
        );
        bytes32 hash = redeemInstructionsHash(redeemInstructions);

        if (tokenId != redeemInstructions.mintToken.tokenId) {
            revert InvalidTokenIdsForTokenType();
        }
        if (!redeemInstructionsHashIsAllowed[tokenId][hash]) {
            revert RedeemInstructionNotAllowed();
        }
        if (redeemInstructions.saleStart > block.timestamp) {
            revert SaleHasNotStarted();
        }
        if (redeemInstructions.saleEnd < block.timestamp) {
            revert SaleEnded();
        }
        if (redeemInstructions.instructions.length != tokenIds.length) {
            revert IncorrectNumberOfTokenIds();
        }
        if (ethValueSent != redeemInstructions.ethAmount) {
            revert WrongValueSent();
        }
        if (amount != redeemInstructions.mintToken.amount) {
            revert IncorrectMintAmount();
        }

        uint256 numInstructions = redeemInstructions.instructions.length;

        unchecked {
            for (uint256 i; i < numInstructions; ++i) {
                RedeemInstruction memory instruction = redeemInstructions.instructions[i];
                if (instruction.tokenType == TokenType.ERC1155) {
                    _handleErc1155Redeem(sender, instruction, tokenIds[i], amounts[i]);
                } else if (instruction.tokenType == TokenType.ERC721) {
                    _handleErc721Redeem(sender, instruction, tokenIds[i]);
                } else if (instruction.tokenType == TokenType.ERC20) {
                    _handleErc20Redeem(sender, instruction);
                }
            }
        }

        bool shouldTransferFunds = redeemInstructions.ethRecipient != address(0);
        commands.setSize(shouldTransferFunds ? 2 : 1);
        commands.mint(sender, tokenId, amount);

        if (shouldTransferFunds) {
            commands.transfer(redeemInstructions.ethRecipient, ethValueSent);
        }

        emit RedeemProcessed(creatorContract, hash, sender, tokenIds, amounts);
    }

    function _handleErc721Redeem(
        address sender,
        RedeemInstruction memory instruction,
        uint256[] memory tokenIds
    )
        internal
    {
        uint256 numTokenIds = tokenIds.length;

        if (numTokenIds != instruction.amount) {
            revert IncorrectBurnOrTransferAmount();
        }

        unchecked {
            for (uint256 j; j < numTokenIds; j++) {
                if (tokenIds[j] < instruction.tokenIdStart || tokenIds[j] > instruction.tokenIdEnd) {
                    revert TokenIdOutOfRange();
                }
                if (instruction.burnFunction != 0) {
                    if (IERC721(instruction.tokenContract).ownerOf(tokenIds[j]) != sender) {
                        revert SenderIsNotTokenOwner();
                    }
                    (bool success,) =
                        instruction.tokenContract.call(abi.encodeWithSelector(instruction.burnFunction, tokenIds[j]));
                    if (!success) {
                        revert BurnFailed();
                    }
                } else {
                    IERC721(instruction.tokenContract).safeTransferFrom(
                        sender, instruction.transferRecipient, tokenIds[j]
                    );
                }
            }
        }
    }

    function _handleErc1155Redeem(
        address sender,
        RedeemInstruction memory instruction,
        uint256[] memory tokenIds,
        uint256[] memory amounts
    )
        internal
    {
        uint256 numTokenIds = tokenIds.length;

        if (amounts.length != numTokenIds) {
            revert IncorrectNumberOfTokenIds();
        }
        uint256 sum;
        for (uint256 j = 0; j < numTokenIds;) {
            sum += amounts[j];

            if (tokenIds[j] < instruction.tokenIdStart || tokenIds[j] > instruction.tokenIdEnd) {
                revert TokenIdOutOfRange();
            }

            unchecked {
                ++j;
            }
        }

        if (sum != instruction.amount) {
            revert IncorrectBurnOrTransferAmount();
        }
        if (instruction.burnFunction != 0) {
            (bool success,) = instruction.tokenContract.call(
                abi.encodeWithSelector(instruction.burnFunction, sender, tokenIds, amounts)
            );
            if (!success) {
                revert BurnFailed();
            }
        } else {
            IERC1155(instruction.tokenContract).safeBatchTransferFrom(
                sender, instruction.transferRecipient, tokenIds, amounts, ""
            );
        }
    }

    function _handleErc20Redeem(address sender, RedeemInstruction memory instruction) internal {
        if (instruction.burnFunction != 0) {
            (bool success,) = instruction.tokenContract.call(
                abi.encodeWithSelector(instruction.burnFunction, sender, instruction.amount)
            );
            if (!success) {
                revert BurnFailed();
            }
        } else {
            IERC20(instruction.tokenContract).transferFrom(sender, instruction.transferRecipient, instruction.amount);
        }
    }

    /// @notice Reset sale - Use clearRedeem instead
    function resetSale(uint256) external view override onlyCreatorContract {
        revert MustCallClearRedeem();
    }
}

File 9 of 31 : ICreator1155.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import { IERC165Upgradeable } from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
import { IERC1155MetadataURIUpgradeable } from
    "@openzeppelin/contracts-upgradeable/interfaces/IERC1155MetadataURIUpgradeable.sol";
import { ICreator1155TypesV1 } from "../nft/ICreator1155TypesV1.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";

/// @notice Main interface for the Creator1155 contract
interface ICreator1155 is ICreator1155TypesV1, 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);
    event SetupSoulbound(uint256 indexed tokenId, bool isSoulbound);

    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
    );

    event AdminMinted(address indexed sender, address indexed recipient, uint256 indexed tokenId, uint256 quantity);
    event AdminMintedBatch(address indexed sender, address indexed minter, uint256[] tokenIds, uint256[] quantities);

    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 CannotMintMoreTokens(uint256 tokenId, uint256 quantity, uint256 totalMinted, uint256 maxSupply);

    error Call_TokenIdMismatch();

    error Transfer_NotAllowed();

    /// @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
    /// @param isSoulbound Whether the token is soulbound
    function setupNewToken(string memory tokenURI, uint256 maxSupply, bool isSoulbound) 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;

    function mintFee() external view returns (uint256);

    /// @notice Withdraws all ETH from the contract to the funds recipient address
    function withdraw() external;

    /// @notice Returns the current implementation address
    function implementation() external view returns (address);
}

File 10 of 31 : SharedBaseConstants.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract SharedBaseConstants {
    uint256 public constant CONTRACT_BASE_ID = 0;
}

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

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface 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);
}

File 12 of 31 : IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol)

pragma solidity ^0.8.0;

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

File 13 of 31 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.2;

import "../../utils/Address.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```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;
        require(
            (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),
            "Initializable: contract is already initialized"
        );
        _initialized = 1;
        if (isTopLevelCall) {
            _initializing = true;
        }
        _;
        if (isTopLevelCall) {
            _initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: setting the version to 255 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint8 version) {
        require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
        _initialized = version;
        _initializing = true;
        _;
        _initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        require(!_initializing, "Initializable: contract is initializing");
        if (_initialized != type(uint8).max) {
            _initialized = type(uint8).max;
            emit Initialized(type(uint8).max);
        }
    }

    /**
     * @dev 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;
    }
}

File 14 of 31 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.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 IERC1155 is IERC165 {
    /**
     * @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;
}

File 15 of 31 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

File 16 of 31 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

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

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

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

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

File 17 of 31 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}

File 18 of 31 : SaleStrategy.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import { IERC165Upgradeable } from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
import { IMinter1155 } from "../interfaces/IMinter1155.sol";
import { IContractMetadata } from "../interfaces/IContractMetadata.sol";
import { IVersionedContract } from "../interfaces/IVersionedContract.sol";

/// @notice Sales Strategy Helper contract template on top of IMinter1155
abstract contract SaleStrategy is IMinter1155, IVersionedContract, IContractMetadata {
    /// @notice This function resets the sales configuration for a given tokenId and contract.
    /// @dev This function is intentioned to be called directly from the affected sales contract
    function resetSale(uint256 tokenId) external virtual;

    function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
        return interfaceId == type(IMinter1155).interfaceId || interfaceId == type(IERC165Upgradeable).interfaceId;
    }
}

File 19 of 31 : SaleCommandHelper.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

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

/// @title SaleCommandHelper
/// @notice Helper library for creating commands for the sale contract
library SaleCommandHelper {
    /// @notice Sets the size of commands and initializes command array. Empty entries are skipped by the resolver.
    /// @dev Beware: this removes all previous command entries from memory
    /// @param commandSet command set struct storage.
    /// @param size size to set for the new struct
    function setSize(ICreatorCommands.CommandSet memory commandSet, uint256 size) internal pure {
        commandSet.commands = new ICreatorCommands.Command[](size);
    }

    /// @notice Creates a command to mint a token
    /// @param commandSet The command set to add the command to
    /// @param to The address to mint to
    /// @param tokenId The token ID to mint
    /// @param quantity The quantity of tokens to mint
    function mint(
        ICreatorCommands.CommandSet memory commandSet,
        address to,
        uint256 tokenId,
        uint256 quantity
    )
        internal
        pure
    {
        unchecked {
            commandSet.commands[commandSet.at++] = ICreatorCommands.Command({
                method: ICreatorCommands.CreatorActions.MINT,
                args: abi.encode(to, tokenId, quantity)
            });
        }
    }

    /// @notice Creates a command to transfer ETH
    /// @param commandSet The command set to add the command to
    /// @param to The address to transfer to
    /// @param amount The amount of ETH to transfer
    function transfer(ICreatorCommands.CommandSet memory commandSet, address to, uint256 amount) internal pure {
        unchecked {
            commandSet.commands[commandSet.at++] = ICreatorCommands.Command({
                method: ICreatorCommands.CreatorActions.SEND_ETH,
                args: abi.encode(to, amount)
            });
        }
    }
}

File 20 of 31 : IERC1155MetadataURIUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1155MetadataURI.sol)

pragma solidity ^0.8.0;

import "../token/ERC1155/extensions/IERC1155MetadataURIUpgradeable.sol";

File 21 of 31 : ICreator1155TypesV1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

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

/// @notice Interface for types used across the Creator1155 contract
interface ICreator1155TypesV1 {
    /// @notice Used to store individual token data
    struct TokenData {
        string uri;
        uint256 maxSupply;
        uint256 totalMinted;
        bool isSoulbound;
    }

    /// @notice Used to store contract-level configuration
    struct ContractConfig {
        address owner;
        uint96 __gap1;
        address payable fundsRecipient;
        uint96 __gap2;
        ITransferHookReceiver transferHook;
        uint96 __gap3;
    }
}

File 22 of 31 : IRenderer1155.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import { IERC165Upgradeable } from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";

/// @dev IERC165 type required
interface IRenderer1155 is IERC165Upgradeable {
    /// @notice Called for assigned tokenId, or when token id is globally set to a renderer
    /// @dev contract target is assumed to be msg.sender
    /// @param tokenId token id to get uri for
    function uri(uint256 tokenId) external view returns (string memory);

    /// @notice Only called for tokenId == 0
    /// @dev contract target is assumed to be msg.sender
    function contractURI() external view returns (string memory);

    /// @notice Sets up renderer from contract
    /// @param initData data to setup renderer with
    /// @dev contract target is assumed to be msg.sender
    function setup(bytes memory initData) external;

    // IERC165 type required – set in base helper
}

File 23 of 31 : IOwnable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

interface IOwnable {
    function owner() external returns (address);

    event OwnershipTransferred(address lastOwner, address newOwner);
}

File 24 of 31 : ICreatorRoyaltiesControl.sol
// 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);
}

File 25 of 31 : IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

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

File 26 of 31 : Address.sol
// 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);
        }
    }
}

File 27 of 31 : IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 28 of 31 : IERC1155MetadataURIUpgradeable.sol
// 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);
}

File 29 of 31 : ITransferHookReceiver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import { IERC165Upgradeable } from "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";

interface ITransferHookReceiver is IERC165Upgradeable {
    /// @notice Token transfer batch callback
    /// @param target target contract for transfer
    /// @param operator operator address for transfer
    /// @param from user address for amount transferred
    /// @param to user address for amount transferred
    /// @param ids list of token ids transferred
    /// @param amounts list of values transferred
    /// @param data data as perscribed by 1155 standard
    function onTokenTransferBatch(
        address target,
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    )
        external;

    // IERC165 type required
}

File 30 of 31 : IERC2981.sol
// 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);
}

File 31 of 31 : IERC1155Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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;
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "forge-std/=lib/forge-std/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "solmate/=lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerNotCreator1155","type":"error"},{"inputs":[],"name":"MinterContractAlreadyExists","type":"error"},{"inputs":[],"name":"MinterContractDoesNotExist","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"creatorContract","type":"address"},{"indexed":true,"internalType":"address","name":"minterContract","type":"address"}],"name":"RedeemMinterDeployed","type":"event"},{"inputs":[],"name":"CONTRACT_BASE_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"contractVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"createMinterIfNoneExists","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_creatorContract","type":"address"}],"name":"doesRedeemMinterExistForCreatorContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_creatorContract","type":"address"}],"name":"getDeployedRedeemMinterForCreatorContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_creatorContract","type":"address"}],"name":"predictMinterAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redeemMinterImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"ethValueSent","type":"uint256"},{"internalType":"bytes","name":"minterArguments","type":"bytes"}],"name":"requestMint","outputs":[{"components":[{"components":[{"internalType":"enum ICreatorCommands.CreatorActions","name":"method","type":"uint8"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct ICreatorCommands.Command[]","name":"commands","type":"tuple[]"},{"internalType":"uint256","name":"at","type":"uint256"}],"internalType":"struct ICreatorCommands.CommandSet","name":"commands","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}]

60a08060405234608557611b808181016001600160401b03811183821017606f5782916107e5833903906000f080156063576001600160a01b031660805260405161075a908161008b8239608051818181610340015281816104b401526105560152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fdfe608060408181526004918236101561001657600080fd5b600090813560e01c90816301144201146103c55750806301ffc9a71461036f5780630aace6c31461032b578063384893cd146102f95780633b6118cc146102ce5780636890e5b31461019c57806375d0c0dc14610147578063893427ef1461012b578063a0a8e460146100e25763d3771f951461009257600080fd5b346100df5760203660031901126100df57506100b46100af6103de565b61046b565b90813b156100d057516001600160a01b03909116815260209150f35b5163208a3ea160e21b81529050fd5b80fd5b50903461012757816003193601126101275780516101239161010382610439565b60018252603160f81b6020830152519182916020835260208301906103f9565b0390f35b5080fd5b50346100df57806003193601126100df57610144610505565b80f35b50903461012757816003193601126101275780516101239161016882610439565b601582527452656465656d204d696e74657220466163746f727960581b6020830152519182916020835260208301906103f9565b508290346100df5760a03660031901126100df576101b86103de565b506084359267ffffffffffffffff8085116102c657366023860112156102c65784840135948186116102ca576024809636920101116102c657815190818301908111828210176102b35782959395526060815260209384820191868352835195808752606087019151958582890152865180935260808801988260808560051b8b010198019481925b858410610254578751898c01528a8a038bf35b90919293949598607f198b8203018c528951805160038110156102a15761028e838c8a8095819560019852015191818582015201906103f9565b9b019c0194019291909a9594939a610241565b634e487b7160e01b8652602185528386fd5b634e487b7160e01b845260418552602484fd5b8280fd5b8380fd5b509034610127576020366003190112610127576020906102ef6100af6103de565b3b15159051908152f35b5090346101275760203660031901126101275760209061031a6100af6103de565b90516001600160a01b039091168152f35b509034610127578160031936011261012757517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5091346102c65760203660031901126102c657359063ffffffff60e01b82168092036102c65760209250636890e5b360e01b82149182156103b4575b50519015158152f35b6301ffc9a760e01b149150386103ab565b9050346101275781600319360112610127576020918152f35b600435906001600160a01b03821682036103f457565b600080fd5b919082519283825260005b848110610425575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201610404565b6040810190811067ffffffffffffffff82111761045557604052565b634e487b7160e01b600052604160045260246000fd5b6043605591604051602081019160018060a01b031682526020815261048f81610439565b519020604051903060388301526f5af43d82803e903d91602b57fd5bf3ff60248301527f00000000000000000000000000000000000000000000000000000000000000006014830152733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152012090565b604080516301ffc9a760e01b815263023a443960e31b6004808301919091526020926000928481602481335afa9081156106665784916106c4575b50156106b75761054f3361046b565b3b6106b1577f00000000000000000000000000000000000000000000000000000000000000006e5af43d82803e903d91602b57fd5bf382518681019033825287815261059a81610439565b519020608883901c62ffffff16763d602d80600a3d3981f3363d3d373d3d3d363d7300000017865260789290921b1785526001600160a01b03906037600986f5169384156106705750833b156102c657805163189acdbd60e31b8152338382015291838360248183895af180156106665761063a575b5050507fda720a7f7472c1be9a29f17b1cb7d747429a2f4f1c450101bdab1fc466e6abff339180a3565b67ffffffffffffffff8311610653575052388080610610565b634e487b7160e01b845260419052602483fd5b82513d86823e3d90fd5b905162461bcd60e51b815291820152601760248201527f455243313136373a2063726561746532206661696c65640000000000000000006044820152606490fd5b50505050565b51638f8aa0d160e01b8152fd5b9050843d861161071d575b601f8101601f1916820167ffffffffffffffff81118382101761070a57869183918552810103126102ca575180151581036102ca5738610540565b634e487b7160e01b865260418552602486fd5b503d6106cf56fea264697066735822122098f51e1906eeb91ed0e8c6d91c12409db88ba7a4418b2c9b50e264829f000d7d64736f6c6343000819003360808060405234601557611b65908161001b8239f35b600080fdfe608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a71461121d57508063029d2c7714610f6a5780630c2b683e14610f2857806319b45c4f14610ef3578063343e3bd414610eb45780633dae35ce14610e8b5780636890e5b3146103e3578063710011f5146103a457806375d0c0dc14610346578063a0a8e46014610300578063c3aea1fc146101fd5763c4d66de8146100a357600080fd5b346101f85760203660031901126101f8576100bc6112d4565b6000549060ff8260081c1615918280936101eb575b80156101d4575b156101785760ff19811660011760005582610166575b506001600160a01b03168015610154576bffffffffffffffffffffffff60a01b600254161760025561011c57005b61ff0019600054166000557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a1005b604051633769579f60e21b8152600490fd5b61ffff191661010117600055386100ee565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b50303b1580156100d85750600160ff8216146100d8565b50600160ff8216106100d1565b600080fd5b346101f85760403660031901126101f857600435602480356001600160401b03918282116101f857366023830112156101f85781600401359283116101f8576005938360051b9436602487860101116101f8576002546001600160a01b039390841633036102ee5760005b8681106102bd575050505060025416926040519260018060fb1b03106101f85780602484930183378101039020907f0910989ccfb0d1cbcfc8beed74e1bf54b662fd84700e4e818ffe2937a8dbe20c600080a3005b6001908460005260208281526040600020908483871b8a01013560005252604060002060ff19815416905501610268565b6040516317162a6b60e01b8152600490fd5b346101f85760003660031901126101f85761034260405161032081611285565b60018152603160f81b60208201526040519182916020835260208301906114e7565b0390f35b346101f85760003660031901126101f85761034260405161036681611285565b601b81527f52656465656d204d696e7465722053616c65205374726174656779000000000060208201526040519182916020835260208301906114e7565b346101f8576003196020368201126101f857600435906001600160401b0382116101f8576101209082360301126101f8576103e190600401611872565b005b346101f85760a03660031901126101f8576103fc6112d4565b6001600160401b03608435116101f8573660236084350112156101f85760843560040135906001600160401b0382116101f857366024836084350101116101f8576040519161044a83611285565b60608352600060208401526002546001600160a01b031633036102ee57606060843582810103126101f8576001600160401b0360246084350135116101f8576104a6602482608435010160248060843501356084350101611329565b6001600160401b0360446084350135116101f8576104d860248360843501016024604460843501356084350101611684565b916001600160401b0360646084350135116101f857602461050b9160843501016024606460843501356084350101611684565b9161051582611534565b9360208351015160243503610e7957602435600052600160205260406000208560005260205260ff6040600020541615610e67576001600160401b036040840151164210610e5557426001600160401b0360608501511610610e4357602083015151825103610a9c57608083015160643503610e315760408351015160443503610e1f5760208301515160005b81811061084a57505060a08301516001600160a01b031615801593906108415760ff60025b166105d1816112fe565b906105df60405192836112b3565b8082526105ee601f19916112fe565b0160005b81811061081c57505087526040519360018060a01b038316602086015260243560408601526044356060860152606085528460808101106001600160401b03608087011117610806576106a58560807f088fba8a2928dfd5d2908fdf4ec352f4a15c385db3491a15dbc808c3bb22df79970160405261067360808201611285565b600260808201528060a08101528951608060208c0151928c6020600186019101520161069f838361175a565b5261175a565b50610794575b506106ed60018060a01b0360025416946106df60405194859460018060a01b031685526060602086015260608501906117b8565b9083820360408501526117b8565b0390a3604051602081526060810182519060406020840152815180915260808301602060808360051b86010193019160005b818110610736576020870151604087015285850386f35b90919293607f19868203018452845190815191600383101561077e576107728260406020809594600197829652015191818582015201906114e7565b9601940192910161071f565b634e487b7160e01b600052602160045260246000fd5b60a00151604080516001600160a01b039092166020830152606435908201526107ff906107ce81606081015b03601f1981018352826112b3565b604051906107db82611285565b60018252602082015287516020890151916001830160208b015261069f838361175a565b50866106ab565b634e487b7160e01b600052604160045260246000fd5b60209060405161082b81611285565b60008152606083820152828286010152016105f2565b60ff60016105c7565b61085881602087015161175a565b518051600481101561077e57600203610aae57610875828661175a565b51610880838961175a565b5190805180835103610a9c576000906000905b808210610a21575050602084015103610a0f5760c083018051909387916001600160e01b03199190821615610951576080015194516040519116602082019081526001600160a01b03928316602483015260606044830152600095869593169390928592916109239183916107c09190610911906084850190611784565b83810360231901606485015290611784565b51925af161092f611adb565b501561093f576001905b016105a2565b604051631bc5aabf60e21b8152600490fd5b608081015160a090910151939695506001600160a01b039384169316915050803b156101f85786600060206109cb82966109b96040519a8b988997631759616b60e11b895260018060a01b03166004890152602488015260a0604488015260a4870190611784565b85810360031901606487015290611784565b8284820391600319830160848701525201925af1918215610a03576001926109f4575b50610939565b6109fd906112a0565b896109ee565b6040513d6000823e3d90fd5b60405163daaa81df60e01b8152600490fd5b9091610a2d838661175a565b518101809111610a865791610a42818561175a565b516040870151118015610a6f575b610a5d5760010190610893565b6040516305033e0360e41b8152600490fd5b50610a7a818561175a565b51606087015110610a50565b634e487b7160e01b600052601160045260246000fd5b60405163061103fb60e51b8152600490fd5b8051600481101561077e57600103610ceb57610aca828661175a565b5180519160208101518303610a0f5760005b838110610aef5750505050600190610939565b610af9818461175a565b516040830151118015610cd4575b610a5d5760c08201516001600160e01b03191615610c4c5760808201516001600160a01b03166020610b39838661175a565b516024604051809481936331a9108f60e11b835260048301525afa908115610a0357600091610c0a575b506001600160a01b03888116911603610bf857608082015160c08301516001600160e01b031916906001600160a01b0316610b9e838661175a565b516040519260208401526024830152602482528160608101106001600160401b03606084011117610806578160009291606084930160405282602083519301915af1610be8611adb565b501561093f576001905b01610adc565b6040516308f0688760e11b8152600490fd5b90506020813d602011610c44575b81610c25602093836112b3565b810103126101f857516001600160a01b03811681036101f8578d610b63565b3d9150610c18565b608082015160a08301516001600160a01b03918216929116610c6e828661175a565b51833b156101f857604051632142170760e11b81526001600160a01b038b811660048301529290921660248301526044820152916000908390606490829084905af1918215610a0357600192610cc5575b50610bf2565b610cce906112a0565b8d610cbf565b50610cdf818461175a565b51606083015110610b07565b8051600481101561077e57600314610d07575b50600190610939565b60c0810180516001600160e01b031990811615610d855760808301519151602093840151604051919092169381019384526001600160a01b0387811660248301526044820192909252600093849390921691908390610d6981606481016107c0565b51925af1610d75611adb565b501561093f576001905b90610cfe565b5050608081015160a08201516020928301516040516323b872dd60e01b81526001600160a01b03888116600483015292831660248201526044810191909152929183916064918391600091165af18015610a0357610de7575b50600190610d7f565b6020813d602011610e17575b81610e00602093836112b3565b810103126101f85751801515036101f85788610dde565b3d9150610df3565b60405163a7dcb93b60e01b8152600490fd5b604051632f4613eb60e01b8152600490fd5b604051630bd8a3eb60e01b8152600490fd5b6040516374626dc160e11b8152600490fd5b60405163177c837f60e11b8152600490fd5b60405163d47aa6a960e01b8152600490fd5b346101f85760003660031901126101f8576002546040516001600160a01b039091168152602090f35b346101f85760403660031901126101f85760043560005260016020526040600020602435600052602052602060ff604060002054166040519015158152f35b346101f85760203660031901126101f8576002546001600160a01b031633036102ee5760405163c96a2b8560e01b8152600490fd5b346101f85760203660031901126101f8576004356001600160401b0381116101f857610f62610f5d6020923690600401611329565b611534565b604051908152f35b346101f8576003196040368201126101f857600435906001600160401b03602435116101f8576024356004016101206024353603928301126101f8576002546001600160a01b031633036102ee5760248035013591838303610e7957610fcf82611872565b610fdc610f5d3684611329565b9380600052600160205260406000208560005260205260ff6040600020541661120b5760005260016020526040600020846000526020526040600020600160ff1982541617905560018060a01b036002541692604051926020845261104760018060a01b03916112ea565b1660208401526040830152602435604481013560608401526064013560048110156101f85761107a906080840190611527565b602219016024356084013512156101f85760243560846024350135016001600160401b036004820135116101f85760e0600482013502360360248201136101f85760a061012060a08401526004820135610140840152610160830191602481019160005b600483013581106111775787877f12f109538a3215cb2c274a1f5ea6daca2470f1f87c378182c850ca234c8586258880896001600160401b0361112560a460243501611315565b1660c08301526001600160401b0361114160c460243501611315565b1660e083015260243560e48101356101008401526001600160a01b039061116b90610104016112ea565b166101208301520390a3005b90919293843560048110156101f85760e08083611198600495600195611527565b602089013560208201526040890135604082015260608901356060820152838060a01b036111c860808b016112ea565b166080820152838060a01b036111df888b016112ea565b168782015260c063ffffffff831b6111f8828c01611270565b16908201520196019493920190506110de565b604051632a4f169160e11b8152600490fd5b346101f85760203660031901126101f8576004359063ffffffff60e01b82168092036101f857602091636890e5b360e01b811490811561125f575b5015158152f35b6301ffc9a760e01b14905083611258565b35906001600160e01b0319821682036101f857565b604081019081106001600160401b0382111761080657604052565b6001600160401b03811161080657604052565b90601f801991011681019081106001600160401b0382111761080657604052565b600435906001600160a01b03821682036101f857565b35906001600160a01b03821682036101f857565b6001600160401b0381116108065760051b60200190565b35906001600160401b03821682036101f857565b9190828103610120938482126101f857604080519360c091906001600160401b038387018181118882101761080657879960808098126101f85761014089018281108482111761080657855261137e876112ea565b825260209260e09684890135888c015261010099878a01358b8d015260609460608b013560049560048210156101f8578e01528c5260808a01358381116101f8578a019487601f870112156101f8578535946113d9866112fe565b986113e68b519a8b6112b3565b868a52888c818c019802890101978189116101f8578901965b888810611450575050505050505050509160a095939161144b9593880152611428868401611315565b9087015261143860c08301611315565b60608701528101356080860152016112ea565b910152565b8c888303126101f8578b51908d8201828110898211176114d1578d52883590848210156101f857908252888b01358b830152888d01358d83015284890135858301528d918b91906114a2888c016112ea565b8882015260a06114b3818d016112ea565b908201526114c2898c01611270565b898201528152019701966113ff565b634e487b7160e01b600090815260418652602490fd5b919082519283825260005b848110611513575050826000602080949584010152601f8019910116010190565b6020818301810151848301820152016114f2565b90600482101561077e5752565b6040908151908160208082019481865261016083019184519160018060a01b03928381511682870152828101519460609560608801526060838301519260809360808a015201519361158c60a09560a08a0190611527565b80890151966101209560c0908760c08c01528951809552836101808c019a01956000935b86851061160c5750505050505050509460a091611606968201516001600160401b0380911660e088015260608301511661010087015260808201519086015201511661014083015203601f1981018352826112b3565b51902090565b9193959798999b509193959b998660e06001928f8f90519061162f838351611527565b84820151858401528d80830151908401528682015187840152808883015116888401528882015116888301528863ffffffff841b9101511688820152019d0195019290918d9b999897959694929c9a9c6115b0565b81601f820112156101f857602090803561169d816112fe565b9360406116ad60405196876112b3565b828652848601918560059460051b860101948186116101f857868101935b8685106116dd57505050505050505090565b84356001600160401b0381116101f857820183603f820112156101f8578881013590611708826112fe565b91611715875193846112b3565b808352868b8401918a1b830101918683116101f85791878c94929593015b81811061174a5750508293508152019401936116cb565b80358652948401948c9401611733565b805182101561176e5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b90815180825260208080930193019160005b8281106117a4575050505090565b835185529381019392810192600101611796565b90808251908181526020809101926020808460051b8301019501936000915b8483106117e75750505050505090565b9091929394958480611805600193601f198682030187528a51611784565b98019301930191949392906117d7565b356001600160401b03811681036101f85790565b903590601e19813603018212156101f857018035906001600160401b0382116101f8576020019160e08202360383136101f857565b356001600160a01b03811681036101f85790565b60c09060c081019161188383611815565b926001600160401b0360a094818061189d60a08801611815565b1691161191821592611ac4575b5050611ab25760808201926118bf8484611829565b905015611aa0576118cf8361185e565b6002805490936001600160a01b03929091831690831603611a8e5760608086013596600497888110156101f857600203611a7d5761190d8188611829565b97905060005b8881106119265750505050505050505050565b6119308383611829565b821015611a685760e082020180358b8110156101f85760038103611a24575060408082013515801590611a18575b611a0957505b6001600160e01b03198187018161197a82611b1a565b161515806119f4575b6119e35761199090611b1a565b1615806119cf575b6119be5760200135156119ad57600101611913565b60405163a7dcb93b60e01b81528a90fd5b60405163177b882d60e31b81528b90fd5b50866119dc89830161185e565b1615611998565b60405163177b882d60e31b81528d90fd5b5088611a018b850161185e565b161515611983565b5163d47aa6a960e01b81528b90fd5b5085820135151561195e565b8960018214918215611a5e575b505015611a4d576040858201358183013511611a095750611964565b60405163a1e9dd9d60e01b81528b90fd5b1490508938611a31565b60328b634e487b7160e01b6000525260246000fd5b604051638f89029b60e01b81528890fd5b60405163d2669a5960e01b8152600490fd5b604051632110d6ef60e11b8152600490fd5b60405163077d2f6760e01b8152600490fd5b611acf919250611815565b429116111538806118aa565b3d15611b15573d906001600160401b0382116108065760405191611b09601f8201601f1916602001846112b3565b82523d6000602084013e565b606090565b356001600160e01b0319811681036101f8579056fea26469706673582212201be95b8706a85ce39e8fff5ca3dbeb7773d8b88f73474fcc266b11101e1c0a0c64736f6c63430008190033

Deployed Bytecode

0x608060408181526004918236101561001657600080fd5b600090813560e01c90816301144201146103c55750806301ffc9a71461036f5780630aace6c31461032b578063384893cd146102f95780633b6118cc146102ce5780636890e5b31461019c57806375d0c0dc14610147578063893427ef1461012b578063a0a8e460146100e25763d3771f951461009257600080fd5b346100df5760203660031901126100df57506100b46100af6103de565b61046b565b90813b156100d057516001600160a01b03909116815260209150f35b5163208a3ea160e21b81529050fd5b80fd5b50903461012757816003193601126101275780516101239161010382610439565b60018252603160f81b6020830152519182916020835260208301906103f9565b0390f35b5080fd5b50346100df57806003193601126100df57610144610505565b80f35b50903461012757816003193601126101275780516101239161016882610439565b601582527452656465656d204d696e74657220466163746f727960581b6020830152519182916020835260208301906103f9565b508290346100df5760a03660031901126100df576101b86103de565b506084359267ffffffffffffffff8085116102c657366023860112156102c65784840135948186116102ca576024809636920101116102c657815190818301908111828210176102b35782959395526060815260209384820191868352835195808752606087019151958582890152865180935260808801988260808560051b8b010198019481925b858410610254578751898c01528a8a038bf35b90919293949598607f198b8203018c528951805160038110156102a15761028e838c8a8095819560019852015191818582015201906103f9565b9b019c0194019291909a9594939a610241565b634e487b7160e01b8652602185528386fd5b634e487b7160e01b845260418552602484fd5b8280fd5b8380fd5b509034610127576020366003190112610127576020906102ef6100af6103de565b3b15159051908152f35b5090346101275760203660031901126101275760209061031a6100af6103de565b90516001600160a01b039091168152f35b509034610127578160031936011261012757517f000000000000000000000000b5adea4ead674d55c4ff526f1f2dc9bec3676efc6001600160a01b03168152602090f35b5091346102c65760203660031901126102c657359063ffffffff60e01b82168092036102c65760209250636890e5b360e01b82149182156103b4575b50519015158152f35b6301ffc9a760e01b149150386103ab565b9050346101275781600319360112610127576020918152f35b600435906001600160a01b03821682036103f457565b600080fd5b919082519283825260005b848110610425575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201610404565b6040810190811067ffffffffffffffff82111761045557604052565b634e487b7160e01b600052604160045260246000fd5b6043605591604051602081019160018060a01b031682526020815261048f81610439565b519020604051903060388301526f5af43d82803e903d91602b57fd5bf3ff60248301527f000000000000000000000000b5adea4ead674d55c4ff526f1f2dc9bec3676efc6014830152733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152012090565b604080516301ffc9a760e01b815263023a443960e31b6004808301919091526020926000928481602481335afa9081156106665784916106c4575b50156106b75761054f3361046b565b3b6106b1577f000000000000000000000000b5adea4ead674d55c4ff526f1f2dc9bec3676efc6e5af43d82803e903d91602b57fd5bf382518681019033825287815261059a81610439565b519020608883901c62ffffff16763d602d80600a3d3981f3363d3d373d3d3d363d7300000017865260789290921b1785526001600160a01b03906037600986f5169384156106705750833b156102c657805163189acdbd60e31b8152338382015291838360248183895af180156106665761063a575b5050507fda720a7f7472c1be9a29f17b1cb7d747429a2f4f1c450101bdab1fc466e6abff339180a3565b67ffffffffffffffff8311610653575052388080610610565b634e487b7160e01b845260419052602483fd5b82513d86823e3d90fd5b905162461bcd60e51b815291820152601760248201527f455243313136373a2063726561746532206661696c65640000000000000000006044820152606490fd5b50505050565b51638f8aa0d160e01b8152fd5b9050843d861161071d575b601f8101601f1916820167ffffffffffffffff81118382101761070a57869183918552810103126102ca575180151581036102ca5738610540565b634e487b7160e01b865260418552602486fd5b503d6106cf56fea264697066735822122098f51e1906eeb91ed0e8c6d91c12409db88ba7a4418b2c9b50e264829f000d7d64736f6c63430008190033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.