ETH Price: $3,099.46 (+0.52%)
Gas: 9 Gwei

Contract

0x70b4070953cDf0cf33D69322495df78A83B734E9
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value

There are no matching entries

Please try again later

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To Value
177942822023-07-28 21:39:23347 days ago1690580363  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BurnRedeemLib

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 150 runs

Other Settings:
default evmVersion
File 1 of 6 : BurnRedeemLib.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/////////////////////////////////////////////////////////////////////////////////////
//                                                                                 //
//                                                                                 //
//                                     .%(#.                                       //
//                                      #(((#%,                                    //
//                                      (#(((((#%*                                 //
//                                      /#((((((((##*                              //
//                                      (#((((((((((##%.                           //
//                                     ,##(/*/(////((((#%*                         //
//                                   .###(//****/////(((##%,                       //
//                  (,          ,%#((((((///******/////((##%(                      //
//                *((,         ,##(///////*********////((###%*                     //
//              /((((         ,##(//////************/(((((###%                     //
//             /((((         ,##((////***************/((((###%                     //
//             (((          .###((///*****************((((####                     //
//             .            (##((//*******************((((##%*                     //
//               (#.       .###((/********************((((##%.      %.             //
//             ,%(#.       .###(/********,,,,,,,*****/(((###%#     ((%,            //
//            /%#/(/       /###(//****,,,,,,,,,,,****/((((((##%%%%#((#%.           //
//           /##(//(#.    ,###((/****,,,,,,,,,,,,,***/((/(((((((((#####%           //
//          *%##(/////((###((((/***,,,,,,,,,,,,,,,***//((((((((((####%%%/          //
//          ####(((//////(//////**,,,,,,.....,,,,,,****/(((((//((####%%%%          //
//         .####(((/((((((/////**,,,,,.......,,,,,,,,*****/////(#####%%%%          //
//         .#%###((////(((//***,,,,,,..........,,,,,,,,*****//((#####%%%%          //
//          /%%%###/////*****,,,,,,,..............,,,,,,,****/(((####%%%%          //
//           /%%###(////****,,,,,,.....        ......,,,,,,**(((####%%%%           //
//            ,#%###(///****,,,,,....            .....,,,,,***/(/(##%%(            //
//              (####(//****,,....                 ....,,,,,***/(####              //
//                (###(/***,,,...                    ...,,,,***(##/                //
//             #.   (#((/**,,,,..                    ...,,,,*((#,                  //
//               ,#(##(((//,,,,..                   ...,,,*/(((#((/                //
//                  *#(((///*,,....                ....,*//((((                    //
//                      *(///***,....            ...,***//,                        //
//                           ,//***,...       ..,,*,                               //
//                                                                                 //
//                                                                                 //
/////////////////////////////////////////////////////////////////////////////////////

import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "./IBurnRedeemCore.sol";

/**
 * @title Burn Redeem Lib
 * @author manifold.xyz
 * @notice Library for Burn Redeem shared extensions.
 */
library BurnRedeemLib {

    event BurnRedeemInitialized(address indexed creatorContract, uint256 indexed instanceId, address initializer);
    event BurnRedeemUpdated(address indexed creatorContract, uint256 indexed instanceId);
    event BurnRedeemMint(address indexed creatorContract, uint256 indexed instanceId, uint256 indexed tokenId, uint32 redeemedCount, bytes data);

    error BurnRedeemAlreadyInitialized();
    error InvalidBurnItem();
    error InvalidBurnToken();
    error InvalidMerkleProof();
    error InvalidStorageProtocol();
    error InvalidPaymentReceiver();
    error InvalidDates();
    error InvalidInput();

    /**
     * Initialiazes a burn redeem with base parameters
     */
    function initialize(
        address creatorContractAddress,
        uint8 creatorContractVersion,
        uint256 instanceId,
        IBurnRedeemCore.BurnRedeem storage burnRedeemInstance,
        IBurnRedeemCore.BurnRedeemParameters calldata burnRedeemParameters
    ) public {
        // Sanity checks
        if (burnRedeemInstance.storageProtocol != IBurnRedeemCore.StorageProtocol.INVALID) {
            revert BurnRedeemAlreadyInitialized();
        }
        _validateParameters(burnRedeemParameters);

        // Create the burn redeem
        burnRedeemInstance.contractVersion = creatorContractVersion;
        _setParameters(burnRedeemInstance, burnRedeemParameters);
        _setBurnGroups(burnRedeemInstance, burnRedeemParameters.burnSet);

        emit BurnRedeemInitialized(creatorContractAddress, instanceId, msg.sender);
    }

    /**
     * Updates a burn redeem with base parameters
     */
    function update(
        address creatorContractAddress,
        uint256 instanceId,
        IBurnRedeemCore.BurnRedeem storage burnRedeemInstance,
        IBurnRedeemCore.BurnRedeemParameters calldata burnRedeemParameters
    ) public {
        // Sanity checks
        if (burnRedeemInstance.storageProtocol == IBurnRedeemCore.StorageProtocol.INVALID) {
            revert IBurnRedeemCore.BurnRedeemDoesNotExist(instanceId);
        }
        _validateParameters(burnRedeemParameters);
        // The current redeemedCount must be divisible by redeemAmount
        if (burnRedeemInstance.redeemedCount % burnRedeemParameters.redeemAmount != 0) {
            revert IBurnRedeemCore.InvalidRedeemAmount();
        }

        // Overwrite the existing burnRedeem
        _setParameters(burnRedeemInstance, burnRedeemParameters);
        _setBurnGroups(burnRedeemInstance, burnRedeemParameters.burnSet);
        syncTotalSupply(burnRedeemInstance);
        emit BurnRedeemUpdated(creatorContractAddress, instanceId);
    }

    /**
     * Helper to update total supply if redeemedCount exceeds totalSupply after airdrop or instance update.
     */
    function syncTotalSupply(IBurnRedeemCore.BurnRedeem storage burnRedeemInstance) public {
        if (
            burnRedeemInstance.totalSupply != 0 &&
            burnRedeemInstance.redeemedCount > burnRedeemInstance.totalSupply
        ) {
            burnRedeemInstance.totalSupply = burnRedeemInstance.redeemedCount;
        }
    }

    /*
     * Helper to validate burn item
     */
    function validateBurnItem(IBurnRedeemCore.BurnItem memory burnItem, address contractAddress, uint256 tokenId, bytes32[] memory merkleProof) public pure {
        if (burnItem.validationType == IBurnRedeemCore.ValidationType.ANY) {
            return;
        }
        if (contractAddress != burnItem.contractAddress) {
            revert InvalidBurnToken();
        }
        if (burnItem.validationType == IBurnRedeemCore.ValidationType.CONTRACT) {
            return;
        } else if (burnItem.validationType == IBurnRedeemCore.ValidationType.RANGE) {
            if (tokenId < burnItem.minTokenId || tokenId > burnItem.maxTokenId) {
                revert IBurnRedeemCore.InvalidToken(tokenId);
            }
            return;
        } else if (burnItem.validationType == IBurnRedeemCore.ValidationType.MERKLE_TREE) {
            bytes32 leaf = keccak256(abi.encodePacked(tokenId));
            if (!MerkleProof.verify(merkleProof, burnItem.merkleRoot, leaf)) {
                revert InvalidMerkleProof();
            }
            return;
        }
        revert InvalidBurnItem();
    }

        /**
     * Helper to validate the parameters for a burn redeem
     */
    function _validateParameters(IBurnRedeemCore.BurnRedeemParameters calldata burnRedeemParameters) internal pure {
        if (burnRedeemParameters.storageProtocol == IBurnRedeemCore.StorageProtocol.INVALID) {
            revert InvalidStorageProtocol();
        }
        if (burnRedeemParameters.paymentReceiver == address(0)) {
            revert InvalidPaymentReceiver();
        }
        if (burnRedeemParameters.endDate != 0 && burnRedeemParameters.startDate >= burnRedeemParameters.endDate) {
            revert InvalidDates();
        }
        if (burnRedeemParameters.totalSupply % burnRedeemParameters.redeemAmount != 0) {
            revert IBurnRedeemCore.InvalidRedeemAmount();
        }
    }

    /**
     * Helper to set top level properties for a burn redeem
     */
    function _setParameters(IBurnRedeemCore.BurnRedeem storage burnRedeemInstance, IBurnRedeemCore.BurnRedeemParameters calldata burnRedeemParameters) private {
        burnRedeemInstance.startDate = burnRedeemParameters.startDate;
        burnRedeemInstance.endDate = burnRedeemParameters.endDate;
        burnRedeemInstance.redeemAmount = burnRedeemParameters.redeemAmount;
        burnRedeemInstance.totalSupply = burnRedeemParameters.totalSupply;
        burnRedeemInstance.storageProtocol = burnRedeemParameters.storageProtocol;
        burnRedeemInstance.location = burnRedeemParameters.location;
        burnRedeemInstance.cost = burnRedeemParameters.cost;
        burnRedeemInstance.paymentReceiver = burnRedeemParameters.paymentReceiver;
    }

    /**
     * Helper to set the burn groups for a burn redeem
     */
    function _setBurnGroups(IBurnRedeemCore.BurnRedeem storage burnRedeemInstance, IBurnRedeemCore.BurnGroup[] calldata burnGroups) private {
        delete burnRedeemInstance.burnSet;
        for (uint256 i; i < burnGroups.length;) {
            burnRedeemInstance.burnSet.push();
            IBurnRedeemCore.BurnGroup storage burnGroup = burnRedeemInstance.burnSet[i];
            if (burnGroups[i].requiredCount == 0 || burnGroups[i].requiredCount > burnGroups[i].items.length) {
                revert InvalidInput();
            }
            burnGroup.requiredCount = burnGroups[i].requiredCount;
            for (uint256 j; j < burnGroups[i].items.length;) {
                IBurnRedeemCore.BurnItem memory burnItem = burnGroups[i].items[j];
                IBurnRedeemCore.TokenSpec tokenSpec = burnItem.tokenSpec;
                uint256 amount = burnItem.amount;
                if (
                    !(
                        (tokenSpec == IBurnRedeemCore.TokenSpec.ERC1155 && amount > 0) ||
                        (tokenSpec == IBurnRedeemCore.TokenSpec.ERC721 && amount == 0)
                    ) || 
                    burnItem.validationType == IBurnRedeemCore.ValidationType.INVALID
                ) {
                    revert InvalidInput();
                }
                burnGroup.items.push(burnGroups[i].items[j]);
                unchecked { ++j; }
            }
            unchecked { ++i; }
        }
    }

}

File 2 of 6 : MerkleProof.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The tree and the proofs can be generated using our
 * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
 * You will find a quickstart guide in the readme.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 * OpenZeppelin's JavaScript library generates merkle trees that are safe
 * against this attack out of the box.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Calldata version of {verify}
     *
     * _Available since v4.7._
     */
    function verifyCalldata(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Calldata version of {processProof}
     *
     * _Available since v4.7._
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * _Available since v4.7._
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Calldata version of {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

File 3 of 6 : IBurnRedeemCore.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/**
 * Burn Redeem Core interface
 */
interface IBurnRedeemCore is IERC165, IERC721Receiver, IERC1155Receiver  {
    error NotAdmin(address);
    error UnsupportedContractVersion();
    error InvalidToken(uint256);
    error InvalidInput();
    error InvalidTokenSpec();
    error InvalidBurnSpec();
    error InvalidData();
    error TransferFailure();
    
    error BurnRedeemDoesNotExist(uint256);
    error BurnRedeemInactive(uint256);

    error InvalidBurnAmount();
    error InvalidRedeemAmount();
    error InvalidPaymentAmount();


    enum StorageProtocol { INVALID, NONE, ARWEAVE, IPFS }

    /**
     * @notice the validation type used for a `BurnItem`
     * CONTRACT                 any token from a specific contract is valid
     * RANGE                    token IDs within a range (inclusive) are valid
     * MERKLE_TREE              various individual token IDs included in a merkle tree are valid
     * ANY                      any token from any contract
     */
    enum ValidationType { INVALID, CONTRACT, RANGE, MERKLE_TREE, ANY }

    enum TokenSpec { INVALID, ERC721, ERC1155 }
    enum BurnSpec { NONE, MANIFOLD, OPENZEPPELIN }

    /**
     * @notice a `BurnItem` indicates which tokens are eligible to be burned
     * @param validationType    which type of validation used to check that the burn item is 
     *                          satisfied
     * @param tokenSpec         whether the token is an ERC721 or ERC1155
     * @param burnSpec          whether the contract for a token has a `burn` function and, if so,
     *                          what interface
     * @param amount            (only for ERC1155 tokens) the amount (value) required to burn
     * @param minTokenId        (only for RANGE validation) the minimum valid token ID
     * @param maxTokenId        (only for RANGE validation) the maximum valid token ID
     * @param merkleRoot        (only for MERKLE_TREE validation) the root of the merkle tree of
     *                          valid token IDs
     */
    struct BurnItem {
        ValidationType validationType;
        address contractAddress;
        TokenSpec tokenSpec;
        BurnSpec burnSpec;
        uint72 amount;
        uint256 minTokenId;
        uint256 maxTokenId;
        bytes32 merkleRoot;
    }

    /**
     * @notice a `BurnGroup` is a group of valid `BurnItem`s
     * @param requiredCount     the number of `BurnItem`s (0 < requiredCount <= items.length) that 
     *                          need to be included in a burn
     * @param items             the list of `BurnItem`s
     */
    struct BurnGroup {
        uint256 requiredCount;
        BurnItem[] items;
    }

    /**
     * @notice parameters for burn redeem intialization/updates
     * @param paymentReceiver   the address to forward proceeds from paid burn redeems
     * @param storageProtocol   the type of storage used for the redeem token URIs
     * @param redeemAmount      the number of redeem tokens to mint for each burn redeem
     * @param totalSupply       the maximum number of redeem tokens to mint (0 for unlimited)
     * @param startDate         the starting time for the burn redeem (0 for immediately)
     * @param endDate           the end time for the burn redeem (0 for never)
     * @param cost              the cost for each burn redeem
     * @param location          used to construct the token URI (Arweave hash, full URI, etc.)
     * @param burnSet           a list of `BurnGroup`s that must each be satisfied for a burn redeem
     */
    struct BurnRedeemParameters {
        address payable paymentReceiver;
        StorageProtocol storageProtocol;
        uint16 redeemAmount;
        uint32 totalSupply;
        uint48 startDate;
        uint48 endDate;
        uint160 cost;
        string location;
        BurnGroup[] burnSet;
    }

    struct BurnRedeem {
        address payable paymentReceiver;
        StorageProtocol storageProtocol;
        uint32 redeemedCount;
        uint16 redeemAmount;
        uint32 totalSupply;
        uint8 contractVersion;
        uint48 startDate;
        uint48 endDate;
        uint160 cost;
        string location;
        BurnGroup[] burnSet;
    }

    /**
     * @notice a pointer to a `BurnItem` in a `BurnGroup` used in calls to `burnRedeem`
     * @param groupIndex        the index of the `BurnGroup` in `BurnRedeem.burnSet`
     * @param itemIndex         the index of the `BurnItem` in `BurnGroup.items`
     * @param contractAddress   the address of the contract for the token
     * @param id                the token ID
     * @param merkleProof       the merkle proof for the token ID (only for MERKLE_TREE validation)
     */
    struct BurnToken {
        uint48 groupIndex;
        uint48 itemIndex;
        address contractAddress;
        uint256 id;
        bytes32[] merkleProof;
    }

    /**
     * @notice get a burn redeem corresponding to a creator contract and instanceId
     * @param creatorContractAddress    the address of the creator contract
     * @param instanceId                the instanceId of the burn redeem for the creator contract
     * @return BurnRedeem               the burn redeem object
     */
    function getBurnRedeem(address creatorContractAddress, uint256 instanceId) external view returns(BurnRedeem memory);
    
    /**
     * @notice get a burn redeem corresponding to a creator contract and tokenId
     * @param creatorContractAddress    the address of the creator contract
     * @param tokenId                   the token to retrieve the burn redeem for
     * @return                          the burn redeem instanceId and burn redeem object
     */
    function getBurnRedeemForToken(address creatorContractAddress, uint256 tokenId) external view returns(uint256, BurnRedeem memory);

    /**
     * @notice burn tokens and mint a redeem token
     * @param creatorContractAddress    the address of the creator contract
     * @param instanceId                the instanceId of the burn redeem for the creator contract
     * @param burnRedeemCount           the number of burn redeems we want to do
     * @param burnTokens                the tokens to burn with pointers to the corresponding BurnItem requirement
     */
    function burnRedeem(address creatorContractAddress, uint256 instanceId, uint32 burnRedeemCount, BurnToken[] calldata burnTokens) external payable;

    /**
     * @notice burn tokens and mint redeem tokens multiple times in a single transaction
     * @param creatorContractAddresses  the addresses of the creator contracts
     * @param instanceIds               the instanceIds of the burn redeems for the corresponding creator contract
     * @param burnRedeemCounts          the burn redeem counts for each burn
     * @param burnTokens                the tokens to burn for each burn redeem with pointers to the corresponding BurnItem requirement
     */
    function burnRedeem(address[] calldata creatorContractAddresses, uint256[] calldata instanceIds, uint32[] calldata burnRedeemCounts, BurnToken[][] calldata burnTokens) external payable;

    /**
     * @notice burn tokens and mint a redeem token
     * @param creatorContractAddress    the address of the creator contract
     * @param instanceId                the instanceId of the burn redeem for the creator contract
     * @param burnRedeemCount           the number of burn redeems we want to do
     * @param burnTokens                the tokens to burn with pointers to the corresponding BurnItem requirement
     * @param data                      the data to emit with the BurnRedeemMint event
     */
    function burnRedeemWithData(address creatorContractAddress, uint256 instanceId, uint32 burnRedeemCount, BurnToken[] calldata burnTokens, bytes calldata data) external payable;

    /**
     * @notice allow admin to airdrop arbitrary tokens 
     * @param creatorContractAddress    the creator contract to mint tokens for
     * @param instanceId                the instanceId of the burn redeem for the creator contract
     * @param recipients                addresses to airdrop to
     * @param amounts                   number of redeems to perform for each address in recipients
     */
    function airdrop(address creatorContractAddress, uint256 instanceId, address[] calldata recipients, uint32[] calldata amounts) external;

    /**
     * @notice recover a token that was sent to the contract without safeTransferFrom
     * @param tokenAddress              the address of the token contract
     * @param tokenId                   the id of the token
     * @param destination               the address to send the token to
     */
    function recoverERC721(address tokenAddress, uint256 tokenId, address destination) external;

    /**
     * @notice withdraw Manifold fee proceeds from the contract
     * @param recipient                 recepient of the funds
     * @param amount                    amount to withdraw in Wei
     */
    function withdraw(address payable recipient, uint256 amount) external;

    /**
     * @notice set the Manifold Membership contract address
     * @param addr                      the address of the Manifold Membership contract 
     */
    function setMembershipAddress(address addr) external;
}

File 4 of 6 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 5 of 6 : IERC1155Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev _Available since v3.1._
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}

File 6 of 6 : 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);
}

Settings
{
  "remappings": [
    "@ensdomains/=node_modules/@ensdomains/",
    "@manifoldxyz/=node_modules/@manifoldxyz/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "create2-helpers/=lib/create2-helpers/src/",
    "create2-scripts/=lib/create2-helpers/script/",
    "creator-core-solidity/=lib/creator-core-solidity/contracts/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
    "eth-gas-reporter/=node_modules/eth-gas-reporter/",
    "forge-std/=lib/forge-std/src/",
    "hardhat/=node_modules/hardhat/",
    "libraries-solidity/=lib/libraries-solidity/contracts/",
    "murky/=lib/murky/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "operator-filter-registry/=node_modules/operator-filter-registry/",
    "truffle/=node_modules/truffle/",
    "lib/forge-std:ds-test/=lib/forge-std/lib/ds-test/src/",
    "lib/murky:ds-test/=lib/murky/lib/forge-std/lib/ds-test/src/",
    "lib/murky:forge-std/=lib/murky/lib/forge-std/src/",
    "lib/murky:openzeppelin-contracts/=lib/murky/lib/openzeppelin-contracts/",
    "lib/openzeppelin-contracts:ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
    "lib/openzeppelin-contracts:erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "lib/openzeppelin-contracts:forge-std/=lib/openzeppelin-contracts/lib/forge-std/src/",
    "lib/openzeppelin-contracts:openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "lib/openzeppelin-contracts-upgradeable:ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/",
    "lib/openzeppelin-contracts-upgradeable:erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
    "lib/openzeppelin-contracts-upgradeable:forge-std/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/src/",
    "lib/openzeppelin-contracts-upgradeable:openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "lib/operator-filter-registry:ds-test/=lib/operator-filter-registry/lib/ds-test/src/",
    "lib/operator-filter-registry:erc4626-tests/=lib/operator-filter-registry/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "lib/operator-filter-registry:forge-std/=lib/operator-filter-registry/lib/forge-std/src/",
    "lib/operator-filter-registry:openzeppelin-contracts-upgradeable/=lib/operator-filter-registry/lib/openzeppelin-contracts-upgradeable/contracts/",
    "lib/operator-filter-registry:openzeppelin-contracts/=lib/operator-filter-registry/lib/openzeppelin-contracts/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 150
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"name":"BurnRedeemAlreadyInitialized","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"BurnRedeemDoesNotExist","type":"error"},{"inputs":[],"name":"InvalidBurnItem","type":"error"},{"inputs":[],"name":"InvalidBurnToken","type":"error"},{"inputs":[],"name":"InvalidDates","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidMerkleProof","type":"error"},{"inputs":[],"name":"InvalidPaymentReceiver","type":"error"},{"inputs":[],"name":"InvalidRedeemAmount","type":"error"},{"inputs":[],"name":"InvalidStorageProtocol","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"InvalidToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"creatorContract","type":"address"},{"indexed":true,"internalType":"uint256","name":"instanceId","type":"uint256"},{"indexed":false,"internalType":"address","name":"initializer","type":"address"}],"name":"BurnRedeemInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"creatorContract","type":"address"},{"indexed":true,"internalType":"uint256","name":"instanceId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"redeemedCount","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"BurnRedeemMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"creatorContract","type":"address"},{"indexed":true,"internalType":"uint256","name":"instanceId","type":"uint256"}],"name":"BurnRedeemUpdated","type":"event"},{"inputs":[{"components":[{"internalType":"enum IBurnRedeemCore.ValidationType","name":"validationType","type":"IBurnRedeemCore.ValidationType"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"enum IBurnRedeemCore.TokenSpec","name":"tokenSpec","type":"IBurnRedeemCore.TokenSpec"},{"internalType":"enum IBurnRedeemCore.BurnSpec","name":"burnSpec","type":"IBurnRedeemCore.BurnSpec"},{"internalType":"uint72","name":"amount","type":"uint72"},{"internalType":"uint256","name":"minTokenId","type":"uint256"},{"internalType":"uint256","name":"maxTokenId","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"internalType":"struct IBurnRedeemCore.BurnItem","name":"burnItem","type":"tuple"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"validateBurnItem","outputs":[],"stateMutability":"pure","type":"function"}]

61139761003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100565760003560e01c806314765c6b1461005b57806372acbd281461007d578063b40609bf14610090578063e5c986cd146100b0575b600080fd5b81801561006757600080fd5b5061007b610076366004610b4b565b6100d0565b005b61007b61008b366004610d0d565b610196565b81801561009c57600080fd5b5061007b6100ab366004610de6565b6102f2565b8180156100bc57600080fd5b5061007b6100cb366004610e49565b6103ed565b60008254600160a01b900460ff1660038111156100ef576100ef610e62565b1461010d57604051630dd0d7ed60e21b815260040160405180910390fd5b6101168161044d565b81546001600160f81b0316600160f81b60ff8616021782556101388282610588565b61014f8261014a610100840184610e78565b610714565b60405133815283906001600160a01b038716907ff4d614881eb59d4bcd5ea596b177a55b560306371604a9490ca2a5c2f24df14d9060200160405180910390a35050505050565b6004845160048111156101ab576101ab610e62565b146102ec5783602001516001600160a01b0316836001600160a01b0316146101e6576040516372ba210360e11b815260040160405180910390fd5b6001845160048111156101fb576101fb610e62565b146102ec5760028451600481111561021557610215610e62565b0361025a578360a0015182108061022f57508360c0015182115b156102555760405163124bad6360e31b8152600481018390526024015b60405180910390fd5b6102ec565b60038451600481111561026f5761026f610e62565b036102d35760008260405160200161028991815260200190565b6040516020818303038152906040528051906020012090506102b0828660e00151836109ef565b6102cd5760405163582f497d60e11b815260040160405180910390fd5b506102ec565b604051637778cc5f60e01b815260040160405180910390fd5b50505050565b60008254600160a01b900460ff16600381111561031157610311610e62565b0361033257604051630e50afef60e21b81526004810184905260240161024c565b61033b8161044d565b61034b6060820160408301610ec9565b82546103689161ffff1690600160a81b900463ffffffff16610eed565b63ffffffff161561038c5760405163918e94c560e01b815260040160405180910390fd5b6103968282610588565b6103a88261014a610100840184610e78565b6103b1826103ed565b60405183906001600160a01b038616907fc4487c68aeaaea10bc0e1e6408497e8b1eedeb6aeece8711fdb0da6b6c288dab90600090a350505050565b8054600160d81b900463ffffffff16158015906104205750805463ffffffff600160d81b82048116600160a81b90920416115b1561044a578054600160d81b63ffffffff600160a81b8304160263ffffffff60d81b199091161781555b50565b600061045f6040830160208401610f1e565b600381111561047057610470610e62565b0361048e5760405163cc14845760e01b815260040160405180910390fd5b600061049d6020830183610f3f565b6001600160a01b0316036104c4576040516301ed76a760e61b815260040160405180910390fd5b6104d460c0820160a08301610f5c565b65ffffffffffff161580159061051857506104f560c0820160a08301610f5c565b65ffffffffffff1661050d60a0830160808401610f5c565b65ffffffffffff1610155b156105365760405163364dd21b60e21b815260040160405180910390fd5b6105466060820160408301610ec9565b61ffff1661055a6080830160608401610f84565b6105649190610eed565b63ffffffff161561044a5760405163918e94c560e01b815260040160405180910390fd5b61059860a0820160808301610f5c565b60018301805465ffffffffffff191665ffffffffffff929092169190911790556105c860c0820160a08301610f5c565b60018301805465ffffffffffff929092166601000000000000026bffffffffffff000000000000199092169190911790556106096060820160408301610ec9565b825461ffff91909116600160c81b0261ffff60c81b199091161782556106356080820160608301610f84565b825463ffffffff91909116600160d81b0263ffffffff60d81b199091161782556106656040820160208301610f1e565b8254839060ff60a01b1916600160a01b83600381111561068757610687610e62565b021790555061069960e0820182610faa565b60028401916106a9919083611074565b506106ba60e0820160c08301610f3f565b6001830180546001600160a01b0392909216600160601b026bffffffffffffffffffffffff9092169190911790556106f56020820182610f3f565b82546001600160a01b0319166001600160a01b03919091161790915550565b610722600384016000610a84565b60005b818110156102ec57600384018054600101808255600082815291908390811061075057610750611135565b9060005260206000209060020201905083838381811061077257610772611135565b9050602002810190610784919061114b565b3515806107e7575083838381811061079e5761079e611135565b90506020028101906107b0919061114b565b6107be90602081019061116b565b90508484848181106107d2576107d2611135565b90506020028101906107e4919061114b565b35115b156108055760405163b4fa3fb360e01b815260040160405180910390fd5b83838381811061081757610817611135565b9050602002810190610829919061114b565b35815560005b84848481811061084157610841611135565b9050602002810190610853919061114b565b61086190602081019061116b565b90508110156109e557600085858581811061087e5761087e611135565b9050602002810190610890919061114b565b61089e90602081019061116b565b838181106108ae576108ae611135565b905061010002018036038101906108c591906111b5565b604081015160808201519192509068ffffffffffffffffff1660028260028111156108f2576108f2610e62565b1480156108ff5750600081115b806109245750600182600281111561091957610919610e62565b148015610924575080155b1580610942575060008351600481111561094057610940610e62565b145b156109605760405163b4fa3fb360e01b815260040160405180910390fd5b8460010188888881811061097657610976611135565b9050602002810190610988919061114b565b61099690602081019061116b565b868181106109a6576109a6611135565b835460018101855560009485526020909420610100909102929092019260040290910190506109d5828261125b565b505083600101935050505061082f565b5050600101610725565b6000826109fc8584610a05565b14949350505050565b600081815b8451811015610a4a57610a3682868381518110610a2957610a29611135565b6020026020010151610a52565b915080610a428161133a565b915050610a0a565b509392505050565b6000818310610a6e576000828152602084905260409020610a7d565b60008381526020839052604090205b9392505050565b508054600082556002029060005260206000209081019061044a91905b80821115610ac4576000808255610abb6001830182610ac8565b50600201610aa1565b5090565b508054600082556004029060005260206000209081019061044a91905b80821115610ac457600080825560018201819055600282018190556003820155600401610ae5565b6001600160a01b038116811461044a57600080fd5b8035610b2d81610b0d565b919050565b60006101208284031215610b4557600080fd5b50919050565b600080600080600060a08688031215610b6357600080fd5b8535610b6e81610b0d565b9450602086013560ff81168114610b8457600080fd5b93506040860135925060608601359150608086013567ffffffffffffffff811115610bae57600080fd5b610bba88828901610b32565b9150509295509295909350565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610c0657610c06610bc7565b604052919050565b6005811061044a57600080fd5b6003811061044a57600080fd5b8035610b2d81610c1b565b68ffffffffffffffffff8116811461044a57600080fd5b8035610b2d81610c33565b6000610100808385031215610c6957600080fd5b6040519081019067ffffffffffffffff82118183101715610c8c57610c8c610bc7565b8160405280925083359150610ca082610c0e565b818152610caf60208501610b22565b6020820152610cc060408501610c28565b6040820152610cd160608501610c28565b6060820152610ce260808501610c4a565b608082015260a084013560a082015260c084013560c082015260e084013560e0820152505092915050565b6000806000806101608587031215610d2457600080fd5b610d2e8686610c55565b9350610100850135610d3f81610b0d565b9250610120850135915061014085013567ffffffffffffffff80821115610d6557600080fd5b818701915087601f830112610d7957600080fd5b8135602082821115610d8d57610d8d610bc7565b8160051b9250610d9e818401610bdd565b828152928401810192818101908b851115610db857600080fd5b948201945b84861015610dd657853582529482019490820190610dbd565b989b979a50959850505050505050565b60008060008060808587031215610dfc57600080fd5b8435610e0781610b0d565b93506020850135925060408501359150606085013567ffffffffffffffff811115610e3157600080fd5b610e3d87828801610b32565b91505092959194509250565b600060208284031215610e5b57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6000808335601e19843603018112610e8f57600080fd5b83018035915067ffffffffffffffff821115610eaa57600080fd5b6020019150600581901b3603821315610ec257600080fd5b9250929050565b600060208284031215610edb57600080fd5b813561ffff81168114610a7d57600080fd5b600063ffffffff80841680610f1257634e487b7160e01b600052601260045260246000fd5b92169190910692915050565b600060208284031215610f3057600080fd5b813560048110610a7d57600080fd5b600060208284031215610f5157600080fd5b8135610a7d81610b0d565b600060208284031215610f6e57600080fd5b813565ffffffffffff81168114610a7d57600080fd5b600060208284031215610f9657600080fd5b813563ffffffff81168114610a7d57600080fd5b6000808335601e19843603018112610fc157600080fd5b83018035915067ffffffffffffffff821115610fdc57600080fd5b602001915036819003821315610ec257600080fd5b600181811c9082168061100557607f821691505b602082108103610b4557634e487b7160e01b600052602260045260246000fd5b601f82111561106f57600081815260208120601f850160051c8101602086101561104c5750805b601f850160051c820191505b8181101561106b57828155600101611058565b5050505b505050565b67ffffffffffffffff83111561108c5761108c610bc7565b6110a08361109a8354610ff1565b83611025565b6000601f8411600181146110d457600085156110bc5750838201355b600019600387901b1c1916600186901b17835561112e565b600083815260209020601f19861690835b8281101561110557868501358255602094850194600190920191016110e5565b50868210156111225760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b634e487b7160e01b600052603260045260246000fd5b60008235603e1983360301811261116157600080fd5b9190910192915050565b6000808335601e1984360301811261118257600080fd5b83018035915067ffffffffffffffff82111561119d57600080fd5b6020019150600881901b3603821315610ec257600080fd5b600061010082840312156111c857600080fd5b610a7d8383610c55565b600081356111df81610b0d565b92915050565b6003811061044a5761044a610e62565b600081356111df81610c1b565b61120b826111e5565b805460ff60a81b191660a89290921b60ff60a81b16919091179055565b611231826111e5565b805460ff60b01b191660b09290921b60ff60b01b16919091179055565b600081356111df81610c33565b813561126681610c0e565b6005811061127657611276610e62565b60ff1982541660ff82168117835550506112bb611295602084016111d2565b828054610100600160a81b03191660089290921b610100600160a81b0316919091179055565b6112d06112ca604084016111f5565b82611202565b6112e56112df606084016111f5565b82611228565b6113186112f46080840161124e565b8280546001600160b81b031660b89290921b6001600160b81b031916919091179055565b60a0820135600182015560c0820135600282015560e082013560038201555050565b60006001820161135a57634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212206341a1ab274505838622ccaea892bc18cc27596fbf6a96551071e44a8e3a4cbc64736f6c63430008110033

Deployed Bytecode

0x7370b4070953cdf0cf33d69322495df78a83b734e930146080604052600436106100565760003560e01c806314765c6b1461005b57806372acbd281461007d578063b40609bf14610090578063e5c986cd146100b0575b600080fd5b81801561006757600080fd5b5061007b610076366004610b4b565b6100d0565b005b61007b61008b366004610d0d565b610196565b81801561009c57600080fd5b5061007b6100ab366004610de6565b6102f2565b8180156100bc57600080fd5b5061007b6100cb366004610e49565b6103ed565b60008254600160a01b900460ff1660038111156100ef576100ef610e62565b1461010d57604051630dd0d7ed60e21b815260040160405180910390fd5b6101168161044d565b81546001600160f81b0316600160f81b60ff8616021782556101388282610588565b61014f8261014a610100840184610e78565b610714565b60405133815283906001600160a01b038716907ff4d614881eb59d4bcd5ea596b177a55b560306371604a9490ca2a5c2f24df14d9060200160405180910390a35050505050565b6004845160048111156101ab576101ab610e62565b146102ec5783602001516001600160a01b0316836001600160a01b0316146101e6576040516372ba210360e11b815260040160405180910390fd5b6001845160048111156101fb576101fb610e62565b146102ec5760028451600481111561021557610215610e62565b0361025a578360a0015182108061022f57508360c0015182115b156102555760405163124bad6360e31b8152600481018390526024015b60405180910390fd5b6102ec565b60038451600481111561026f5761026f610e62565b036102d35760008260405160200161028991815260200190565b6040516020818303038152906040528051906020012090506102b0828660e00151836109ef565b6102cd5760405163582f497d60e11b815260040160405180910390fd5b506102ec565b604051637778cc5f60e01b815260040160405180910390fd5b50505050565b60008254600160a01b900460ff16600381111561031157610311610e62565b0361033257604051630e50afef60e21b81526004810184905260240161024c565b61033b8161044d565b61034b6060820160408301610ec9565b82546103689161ffff1690600160a81b900463ffffffff16610eed565b63ffffffff161561038c5760405163918e94c560e01b815260040160405180910390fd5b6103968282610588565b6103a88261014a610100840184610e78565b6103b1826103ed565b60405183906001600160a01b038616907fc4487c68aeaaea10bc0e1e6408497e8b1eedeb6aeece8711fdb0da6b6c288dab90600090a350505050565b8054600160d81b900463ffffffff16158015906104205750805463ffffffff600160d81b82048116600160a81b90920416115b1561044a578054600160d81b63ffffffff600160a81b8304160263ffffffff60d81b199091161781555b50565b600061045f6040830160208401610f1e565b600381111561047057610470610e62565b0361048e5760405163cc14845760e01b815260040160405180910390fd5b600061049d6020830183610f3f565b6001600160a01b0316036104c4576040516301ed76a760e61b815260040160405180910390fd5b6104d460c0820160a08301610f5c565b65ffffffffffff161580159061051857506104f560c0820160a08301610f5c565b65ffffffffffff1661050d60a0830160808401610f5c565b65ffffffffffff1610155b156105365760405163364dd21b60e21b815260040160405180910390fd5b6105466060820160408301610ec9565b61ffff1661055a6080830160608401610f84565b6105649190610eed565b63ffffffff161561044a5760405163918e94c560e01b815260040160405180910390fd5b61059860a0820160808301610f5c565b60018301805465ffffffffffff191665ffffffffffff929092169190911790556105c860c0820160a08301610f5c565b60018301805465ffffffffffff929092166601000000000000026bffffffffffff000000000000199092169190911790556106096060820160408301610ec9565b825461ffff91909116600160c81b0261ffff60c81b199091161782556106356080820160608301610f84565b825463ffffffff91909116600160d81b0263ffffffff60d81b199091161782556106656040820160208301610f1e565b8254839060ff60a01b1916600160a01b83600381111561068757610687610e62565b021790555061069960e0820182610faa565b60028401916106a9919083611074565b506106ba60e0820160c08301610f3f565b6001830180546001600160a01b0392909216600160601b026bffffffffffffffffffffffff9092169190911790556106f56020820182610f3f565b82546001600160a01b0319166001600160a01b03919091161790915550565b610722600384016000610a84565b60005b818110156102ec57600384018054600101808255600082815291908390811061075057610750611135565b9060005260206000209060020201905083838381811061077257610772611135565b9050602002810190610784919061114b565b3515806107e7575083838381811061079e5761079e611135565b90506020028101906107b0919061114b565b6107be90602081019061116b565b90508484848181106107d2576107d2611135565b90506020028101906107e4919061114b565b35115b156108055760405163b4fa3fb360e01b815260040160405180910390fd5b83838381811061081757610817611135565b9050602002810190610829919061114b565b35815560005b84848481811061084157610841611135565b9050602002810190610853919061114b565b61086190602081019061116b565b90508110156109e557600085858581811061087e5761087e611135565b9050602002810190610890919061114b565b61089e90602081019061116b565b838181106108ae576108ae611135565b905061010002018036038101906108c591906111b5565b604081015160808201519192509068ffffffffffffffffff1660028260028111156108f2576108f2610e62565b1480156108ff5750600081115b806109245750600182600281111561091957610919610e62565b148015610924575080155b1580610942575060008351600481111561094057610940610e62565b145b156109605760405163b4fa3fb360e01b815260040160405180910390fd5b8460010188888881811061097657610976611135565b9050602002810190610988919061114b565b61099690602081019061116b565b868181106109a6576109a6611135565b835460018101855560009485526020909420610100909102929092019260040290910190506109d5828261125b565b505083600101935050505061082f565b5050600101610725565b6000826109fc8584610a05565b14949350505050565b600081815b8451811015610a4a57610a3682868381518110610a2957610a29611135565b6020026020010151610a52565b915080610a428161133a565b915050610a0a565b509392505050565b6000818310610a6e576000828152602084905260409020610a7d565b60008381526020839052604090205b9392505050565b508054600082556002029060005260206000209081019061044a91905b80821115610ac4576000808255610abb6001830182610ac8565b50600201610aa1565b5090565b508054600082556004029060005260206000209081019061044a91905b80821115610ac457600080825560018201819055600282018190556003820155600401610ae5565b6001600160a01b038116811461044a57600080fd5b8035610b2d81610b0d565b919050565b60006101208284031215610b4557600080fd5b50919050565b600080600080600060a08688031215610b6357600080fd5b8535610b6e81610b0d565b9450602086013560ff81168114610b8457600080fd5b93506040860135925060608601359150608086013567ffffffffffffffff811115610bae57600080fd5b610bba88828901610b32565b9150509295509295909350565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610c0657610c06610bc7565b604052919050565b6005811061044a57600080fd5b6003811061044a57600080fd5b8035610b2d81610c1b565b68ffffffffffffffffff8116811461044a57600080fd5b8035610b2d81610c33565b6000610100808385031215610c6957600080fd5b6040519081019067ffffffffffffffff82118183101715610c8c57610c8c610bc7565b8160405280925083359150610ca082610c0e565b818152610caf60208501610b22565b6020820152610cc060408501610c28565b6040820152610cd160608501610c28565b6060820152610ce260808501610c4a565b608082015260a084013560a082015260c084013560c082015260e084013560e0820152505092915050565b6000806000806101608587031215610d2457600080fd5b610d2e8686610c55565b9350610100850135610d3f81610b0d565b9250610120850135915061014085013567ffffffffffffffff80821115610d6557600080fd5b818701915087601f830112610d7957600080fd5b8135602082821115610d8d57610d8d610bc7565b8160051b9250610d9e818401610bdd565b828152928401810192818101908b851115610db857600080fd5b948201945b84861015610dd657853582529482019490820190610dbd565b989b979a50959850505050505050565b60008060008060808587031215610dfc57600080fd5b8435610e0781610b0d565b93506020850135925060408501359150606085013567ffffffffffffffff811115610e3157600080fd5b610e3d87828801610b32565b91505092959194509250565b600060208284031215610e5b57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6000808335601e19843603018112610e8f57600080fd5b83018035915067ffffffffffffffff821115610eaa57600080fd5b6020019150600581901b3603821315610ec257600080fd5b9250929050565b600060208284031215610edb57600080fd5b813561ffff81168114610a7d57600080fd5b600063ffffffff80841680610f1257634e487b7160e01b600052601260045260246000fd5b92169190910692915050565b600060208284031215610f3057600080fd5b813560048110610a7d57600080fd5b600060208284031215610f5157600080fd5b8135610a7d81610b0d565b600060208284031215610f6e57600080fd5b813565ffffffffffff81168114610a7d57600080fd5b600060208284031215610f9657600080fd5b813563ffffffff81168114610a7d57600080fd5b6000808335601e19843603018112610fc157600080fd5b83018035915067ffffffffffffffff821115610fdc57600080fd5b602001915036819003821315610ec257600080fd5b600181811c9082168061100557607f821691505b602082108103610b4557634e487b7160e01b600052602260045260246000fd5b601f82111561106f57600081815260208120601f850160051c8101602086101561104c5750805b601f850160051c820191505b8181101561106b57828155600101611058565b5050505b505050565b67ffffffffffffffff83111561108c5761108c610bc7565b6110a08361109a8354610ff1565b83611025565b6000601f8411600181146110d457600085156110bc5750838201355b600019600387901b1c1916600186901b17835561112e565b600083815260209020601f19861690835b8281101561110557868501358255602094850194600190920191016110e5565b50868210156111225760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b634e487b7160e01b600052603260045260246000fd5b60008235603e1983360301811261116157600080fd5b9190910192915050565b6000808335601e1984360301811261118257600080fd5b83018035915067ffffffffffffffff82111561119d57600080fd5b6020019150600881901b3603821315610ec257600080fd5b600061010082840312156111c857600080fd5b610a7d8383610c55565b600081356111df81610b0d565b92915050565b6003811061044a5761044a610e62565b600081356111df81610c1b565b61120b826111e5565b805460ff60a81b191660a89290921b60ff60a81b16919091179055565b611231826111e5565b805460ff60b01b191660b09290921b60ff60b01b16919091179055565b600081356111df81610c33565b813561126681610c0e565b6005811061127657611276610e62565b60ff1982541660ff82168117835550506112bb611295602084016111d2565b828054610100600160a81b03191660089290921b610100600160a81b0316919091179055565b6112d06112ca604084016111f5565b82611202565b6112e56112df606084016111f5565b82611228565b6113186112f46080840161124e565b8280546001600160b81b031660b89290921b6001600160b81b031916919091179055565b60a0820135600182015560c0820135600282015560e082013560038201555050565b60006001820161135a57634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212206341a1ab274505838622ccaea892bc18cc27596fbf6a96551071e44a8e3a4cbc64736f6c63430008110033

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
Loading...
Loading
[ Download: CSV Export  ]

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