ETH Price: $3,282.00 (-5.49%)

Contract

0x899ce31dF6C6Af81203AcAaD285bF539234eF4b8
 

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Token Holdings

Sponsored

Transaction Hash
Method
Block
From
To
Value
0x60808060971589582023-05-10 2:14:46411 days ago1683684886IN
 Create: ZoraCreatorMerkleMinterStrategy
0 ETH0.000000960.001

View more zero value Internal Transactions in Advanced View mode

Advanced mode:

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ZoraCreatorMerkleMinterStrategy

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 5000 runs

Other Settings:
default evmVersion
File 1 of 13 : ZoraCreatorMerkleMinterStrategy.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {Enjoy} from "_imagine/mint/Enjoy.sol";
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import {IMinter1155} from "../../interfaces/IMinter1155.sol";
import {ICreatorCommands} from "../../interfaces/ICreatorCommands.sol";
import {SaleStrategy} from "../SaleStrategy.sol";
import {ICreatorCommands} from "../../interfaces/ICreatorCommands.sol";
import {SaleCommandHelper} from "../utils/SaleCommandHelper.sol";
import {LimitedMintPerAddress} from "../utils/LimitedMintPerAddress.sol";

/*


             β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘              
        β–‘β–‘β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘        
      β–‘β–‘β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘      
    β–‘β–‘β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    
   β–‘β–“β–“β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘        β–‘β–‘β–‘β–‘β–‘β–‘β–‘    
  β–‘β–“β–“β–“β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘        β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  
  β–‘β–“β–“β–“β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  
  β–‘β–“β–“β–“β–’β–’β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  
  β–‘β–“β–“β–“β–“β–“β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  
   β–‘β–“β–“β–“β–“β–’β–’β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  
    β–‘β–‘β–“β–“β–“β–“β–’β–’β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    
    β–‘β–‘β–“β–“β–“β–“β–“β–“β–’β–’β–’β–’β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–’β–’β–’β–‘β–‘    
      β–‘β–‘β–“β–“β–“β–“β–“β–“β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–‘β–‘      
          β–‘β–‘β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–’β–’β–‘β–‘β–‘          

               OURS TRULY,


    github.com/ourzora/zora-1155-contracts

 */

/// @title ZoraCreatorMerkleMinterStrategy
/// @notice Mints tokens based on a merkle tree, for presales for example
/// @author @iainnash / @tbtstl
contract ZoraCreatorMerkleMinterStrategy is Enjoy, SaleStrategy, LimitedMintPerAddress {
    using SaleCommandHelper for ICreatorCommands.CommandSet;

    /// @notice General merkle sale settings
    struct MerkleSaleSettings {
        /// @notice Unix timestamp for the sale start
        uint64 presaleStart;
        /// @notice Unix timestamp for the sale end
        uint64 presaleEnd;
        /// @notice Funds recipient (0 if no different funds recipient than the contract global)
        address fundsRecipient;
        /// @notice Merkle root for
        bytes32 merkleRoot;
    }

    /// @notice Event for sale configuration updated
    event SaleSet(address indexed mediaContract, uint256 indexed tokenId, MerkleSaleSettings merkleSaleSettings);

    /// @notice Storage for allowed merkle settings for the sales configuration
    mapping(address => mapping(uint256 => MerkleSaleSettings)) public allowedMerkles;
    // target -> tokenId -> settings

    error SaleEnded();
    error SaleHasNotStarted();
    error WrongValueSent();
    error InvalidMerkleProof(address mintTo, bytes32[] merkleProof, bytes32 merkleRoot);

    /// @notice ContractURI for contract information with the strategy
    function contractURI() external pure override returns (string memory) {
        return "https://github.com/ourzora/zora-1155-contracts/";
    }

    /// @notice The name of the sale strategy
    function contractName() external pure override returns (string memory) {
        return "Merkle Tree Sale Strategy";
    }

    /// @notice The version of the sale strategy
    function contractVersion() external pure override returns (string memory) {
        return "1.0.0";
    }

    error MerkleClaimsExceeded();

    /// @notice Compiles and returns the commands needed to mint a token using this sales strategy
    /// @param tokenId The token ID to mint
    /// @param quantity The quantity of tokens to mint
    /// @param ethValueSent The amount of ETH sent with the transaction
    /// @param minterArguments The arguments passed to the minter, which should be the address to mint to, the max quantity, the price per token, and the merkle proof
    function requestMint(
        address,
        uint256 tokenId,
        uint256 quantity,
        uint256 ethValueSent,
        bytes calldata minterArguments
    ) external returns (ICreatorCommands.CommandSet memory commands) {
        (address mintTo, uint256 maxQuantity, uint256 pricePerToken, bytes32[] memory merkleProof) = abi.decode(
            minterArguments,
            (address, uint256, uint256, bytes32[])
        );

        MerkleSaleSettings memory config = allowedMerkles[msg.sender][tokenId];

        // Check sale end
        if (block.timestamp > config.presaleEnd) {
            revert SaleEnded();
        }

        // Check sale start
        if (block.timestamp < config.presaleStart) {
            revert SaleHasNotStarted();
        }

        if (!MerkleProof.verify(merkleProof, config.merkleRoot, keccak256(abi.encode(mintTo, maxQuantity, pricePerToken)))) {
            revert InvalidMerkleProof(mintTo, merkleProof, config.merkleRoot);
        }

        if (maxQuantity > 0) {
            _requireMintNotOverLimitAndUpdate(maxQuantity, quantity, msg.sender, tokenId, mintTo);
        }

        if (quantity * pricePerToken != ethValueSent) {
            revert WrongValueSent();
        }

        // Should transfer funds if funds recipient is set to a non-default address
        bool shouldTransferFunds = config.fundsRecipient != address(0);

        // Setup contract commands
        commands.setSize(shouldTransferFunds ? 2 : 1);

        // Mint command
        commands.mint(mintTo, tokenId, quantity);

        // If we have a non-default funds recipient for this token
        if (shouldTransferFunds) {
            commands.transfer(config.fundsRecipient, ethValueSent);
        }
    }

    /// @notice Sets the sale configuration for a token
    function setSale(uint256 tokenId, MerkleSaleSettings memory merkleSaleSettings) external {
        allowedMerkles[msg.sender][tokenId] = merkleSaleSettings;

        // Emit event for new sale
        emit SaleSet(msg.sender, tokenId, merkleSaleSettings);
    }

    /// @notice Resets the sale configuration for a token
    function resetSale(uint256 tokenId) external override {
        delete allowedMerkles[msg.sender][tokenId];

        // Emit event with empty sale
        emit SaleSet(msg.sender, tokenId, allowedMerkles[msg.sender][tokenId]);
    }

    /// @notice Gets the sale configuration for a token
    /// @param tokenContract address to look up sale for
    /// @param tokenId token ID to look up sale for
    function sale(address tokenContract, uint256 tokenId) external view returns (MerkleSaleSettings memory) {
        return allowedMerkles[tokenContract][tokenId];
    }

    /// @notice IERC165 interface
    /// @param interfaceId intrfaceinterface id to match
    function supportsInterface(bytes4 interfaceId) public pure virtual override(LimitedMintPerAddress, SaleStrategy) returns (bool) {
        return super.supportsInterface(interfaceId) || LimitedMintPerAddress.supportsInterface(interfaceId) || SaleStrategy.supportsInterface(interfaceId);
    }
}

File 2 of 13 : Enjoy.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

/*





             β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘              
        β–‘β–‘β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘        
      β–‘β–‘β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘      
    β–‘β–‘β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    
   β–‘β–“β–“β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘        β–‘β–‘β–‘β–‘β–‘β–‘β–‘    
  β–‘β–“β–“β–“β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘        β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  
  β–‘β–“β–“β–“β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  
  β–‘β–“β–“β–“β–’β–’β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  
  β–‘β–“β–“β–“β–“β–“β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  
   β–‘β–“β–“β–“β–“β–’β–’β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  
    β–‘β–‘β–“β–“β–“β–“β–’β–’β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘    
    β–‘β–‘β–“β–“β–“β–“β–“β–“β–’β–’β–’β–’β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–’β–’β–’β–‘β–‘    
      β–‘β–‘β–“β–“β–“β–“β–“β–“β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–‘β–‘      
          β–‘β–‘β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–’β–’β–‘β–‘β–‘          

               OURS TRULY,











 */

interface Enjoy {

}

File 3 of 13 : 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 4 of 13 : IMinter1155.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

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

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

File 5 of 13 : 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 6 of 13 : SaleStrategy.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {IERC165Upgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/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
/// @author @iainnash / @tbtstl
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 7 of 13 : 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
/// @author @iainnash / @tbtstl
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 8 of 13 : LimitedMintPerAddress.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

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

contract LimitedMintPerAddress is ILimitedMintPerAddress {
    /// @notice Storage for slot to check user mints
    /// @notice target contract -> tokenId -> minter user -> numberMinted
    /// @dev No gap or stroage interface since this is used within non-upgradeable contracts
    mapping(address => mapping(uint256 => mapping(address => uint256))) internal mintedPerAddress;

    function getMintedPerWallet(address tokenContract, uint256 tokenId, address wallet) external view returns (uint256) {
        return mintedPerAddress[tokenContract][tokenId][wallet];
    }

    function _requireMintNotOverLimitAndUpdate(uint256 limit, uint256 numRequestedMint, address tokenContract, uint256 tokenId, address wallet) internal {
        mintedPerAddress[tokenContract][tokenId][wallet] += numRequestedMint;
        if (mintedPerAddress[tokenContract][tokenId][wallet] > limit) {
            revert UserExceedsMintLimit(wallet, limit, mintedPerAddress[tokenContract][tokenId][wallet]);
        }
    }

    function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) {
        return interfaceId == type(ILimitedMintPerAddress).interfaceId;
    }
}

File 9 of 13 : 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 10 of 13 : 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);

    /// @notice Contract URI returns the uri for more information about the given contract
    function contractURI() external returns (string memory);
}

File 11 of 13 : IVersionedContract.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

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

File 12 of 13 : ILimitedMintPerAddress.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

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

interface ILimitedMintPerAddress is IERC165Upgradeable {
    error UserExceedsMintLimit(address user, uint256 limit, uint256 requestedAmount);

    function getMintedPerWallet(address token, uint256 tokenId, address wallet) external view returns (uint256);
}

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

Settings
{
  "remappings": [
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
    "@zoralabs/=node_modules/@zoralabs/",
    "@zoralabs/openzeppelin-contracts-upgradeable/=node_modules/@zoralabs/openzeppelin-contracts-upgradeable/",
    "_imagine/=_imagine/",
    "ds-test/=node_modules/ds-test/src/",
    "forge-std/=node_modules/forge-std/src/",
    "mint/=_imagine/mint/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 5000
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"mintTo","type":"address"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"name":"InvalidMerkleProof","type":"error"},{"inputs":[],"name":"MerkleClaimsExceeded","type":"error"},{"inputs":[],"name":"SaleEnded","type":"error"},{"inputs":[],"name":"SaleHasNotStarted","type":"error"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"name":"UserExceedsMintLimit","type":"error"},{"inputs":[],"name":"WrongValueSent","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"mediaContract","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"uint64","name":"presaleStart","type":"uint64"},{"internalType":"uint64","name":"presaleEnd","type":"uint64"},{"internalType":"address","name":"fundsRecipient","type":"address"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"indexed":false,"internalType":"struct ZoraCreatorMerkleMinterStrategy.MerkleSaleSettings","name":"merkleSaleSettings","type":"tuple"}],"name":"SaleSet","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"allowedMerkles","outputs":[{"internalType":"uint64","name":"presaleStart","type":"uint64"},{"internalType":"uint64","name":"presaleEnd","type":"uint64"},{"internalType":"address","name":"fundsRecipient","type":"address"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"contractVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"wallet","type":"address"}],"name":"getMintedPerWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","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":"uint256","name":"tokenId","type":"uint256"}],"name":"resetSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"sale","outputs":[{"components":[{"internalType":"uint64","name":"presaleStart","type":"uint64"},{"internalType":"uint64","name":"presaleEnd","type":"uint64"},{"internalType":"address","name":"fundsRecipient","type":"address"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"internalType":"struct ZoraCreatorMerkleMinterStrategy.MerkleSaleSettings","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"uint64","name":"presaleStart","type":"uint64"},{"internalType":"uint64","name":"presaleEnd","type":"uint64"},{"internalType":"address","name":"fundsRecipient","type":"address"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"internalType":"struct ZoraCreatorMerkleMinterStrategy.MerkleSaleSettings","name":"merkleSaleSettings","type":"tuple"}],"name":"setSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}]

6080806040523461001657611095908161001c8239f35b600080fdfe608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a714610e4d5750806319b45c4f14610d8b578063515740a614610b9d578063611efc0914610a9f5780636890e5b3146102ca57806370fe2a261461024657806375d0c0dc146101e85780637b49ff2c14610178578063a0a8e4601461011a5763e8a3d4851461008d57600080fd5b34610115576000600319360112610115576101116040516100ad81610f62565b602f81527f68747470733a2f2f6769746875622e636f6d2f6f75727a6f72612f7a6f72612d60208201527f313135352d636f6e7472616374732f00000000000000000000000000000000006040820152604051918291602083526020830190610fc4565b0390f35b600080fd5b346101155760006003193601126101155761011160405161013a81610f46565b600581527f312e302e300000000000000000000000000000000000000000000000000000006020820152604051918291602083526020830190610fc4565b3461011557606060031936011261011557610191610fa1565b6044359073ffffffffffffffffffffffffffffffffffffffff908183168093036101155716600052600060205260406000206024356000526020526040600020906000526020526020604060002054604051908152f35b346101155760006003193601126101155761011160405161020881610f46565b601981527f4d65726b6c6520547265652053616c65205374726174656779000000000000006020820152604051918291602083526020830190610fc4565b3461011557604060031936011261011557608073ffffffffffffffffffffffffffffffffffffffff80610277610fa1565b166000526001602052604060002060243560005260205260406000206002815492600183015416910154906040519267ffffffffffffffff90818116855260401c16602084015260408301526060820152f35b346101155760a0600319360112610115576102e3610fa1565b5067ffffffffffffffff6084351161011557366023608435011215610115576084356004013567ffffffffffffffff81116101155760843501602481013681116101155760806040519261033684610f46565b606084526000602085015260843590031261011557602460843501359173ffffffffffffffffffffffffffffffffffffffff83168303610115576084803501359067ffffffffffffffff8211610115578260438360843501011215610115576024826084350101356103a781611004565b926103b56040519485610f7e565b8184526020840190819560448460051b836084350101011161011557906044826084350101915b60448460051b826084350101018310610a8a5750505050336000526001602052604060002060243560005260205260406000206040519061041c82610f2a565b600267ffffffffffffffff8254818116855260401c169182602085015273ffffffffffffffffffffffffffffffffffffffff6001820154166040850152015460608301524211610a605767ffffffffffffffff8151164210610a36576060810151946040516104eb816104dd606460843501356044608435013573ffffffffffffffffffffffffffffffffffffffff87166020850160409194939273ffffffffffffffffffffffffffffffffffffffff606083019616825260208201520152565b03601f198101835282610f7e565b60208151910120946000955b85518710156105915761050a878761101c565b5190818110156105805760005260205260406000205b957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461055157600101956104f7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b906000526020526040600020610520565b90878692036109a95750506044608435013561084e575b60646084350135604435818102918183041490151715610551576064350361082457604082015173ffffffffffffffffffffffffffffffffffffffff16158015919061081b5760ff60025b16601f1961061961060383611004565b926106116040519485610f7e565b808452611004565b0160005b8181106107f657505084526040805173ffffffffffffffffffffffffffffffffffffffff90921660208301526024359082015260443560608201526106a09061066981608081016104dd565b6040519061067682610f46565b600282526020820152845160208601519160018301602088015261069a838361101c565b5261101c565b50610782575b50604051602081526060810182519060406020840152815180915260808301602060808360051b86010193019160005b8181106106ed576020870151604087015285850386f35b909192937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80868203018452845190815191600383101561075357610747826040602080959460019782965201519181858201520190610fc4565b960194019291016106d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff60406107ef920151166040519060208201526064356040820152604081526107be81610f62565b604051906107cb82610f46565b600182526020820152825160208401519160018301602086015261069a838361101c565b50816106a6565b60209060405161080581610f46565b600081526060838201528282860101520161061d565b60ff60016105f3565b60046040517f2f4613eb000000000000000000000000000000000000000000000000000000008152fd5b3360005260006020526040600020602435600052602052604060002073ffffffffffffffffffffffffffffffffffffffff82166000526020526040600020805460443581018111610551576044350190553360005260006020526040600020602435600052602052604060002073ffffffffffffffffffffffffffffffffffffffff82166000526020526044608435013560406000205411156105a8573360005260006020526040600020602435600052602052604060002073ffffffffffffffffffffffffffffffffffffffff8216600052602052604060002054906109a56040519283927fe2d9156400000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff6044608435013591166004850160409194939273ffffffffffffffffffffffffffffffffffffffff606083019616825260208201520152565b0390fd5b6060840151604051927fedc7572000000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff6064850195166004850152606060248501525180945260848301916000945b808610610a1e57505082935060448301520390fd5b90926020806001928651815201940195019490610a09565b60046040517fe8c4db82000000000000000000000000000000000000000000000000000000008152fd5b60046040517f0bd8a3eb000000000000000000000000000000000000000000000000000000008152fd5b602080604493853581520193019291506103dc565b3461011557604060031936011261011557610111610abb610fa1565b60006060604051610acb81610f2a565b828152826020820152826040820152015273ffffffffffffffffffffffffffffffffffffffff809116600052600160205260406000206024356000526020526002604060002060405192610b1e84610f2a565b815467ffffffffffffffff90818116865260401c16602085015260018201541660408401520154606082015260405191829182919091606080608083019467ffffffffffffffff808251168552602082015116602085015273ffffffffffffffffffffffffffffffffffffffff60408201511660408501520151910152565b346101155760a06003193601126101155760043560807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601126101155760405167ffffffffffffffff6080820181811183821017610d5c5760405260243581811681036101155782526044358181168103610115576020830190815273ffffffffffffffffffffffffffffffffffffffff9060643582811681036101155760029260408601918252606086019260843584523360005260016020526040600020886000526020526040600020958751167fffffffffffffffffffffffffffffffff000000000000000000000000000000006fffffffffffffffff00000000000000008854935160401b16921617178555600185019151167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055519101557f82ae5a22c3160d46d62997cfa6f39886b3126a3701c0e42ff3ce4f0b1b6ad0e360405180610d57339482919091606080608083019467ffffffffffffffff808251168552602082015116602085015273ffffffffffffffffffffffffffffffffffffffff60408201511660408501520151910152565b0390a3005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b346101155760208060031936011261011557600435903360005260018152604060002082600052815260006002604082208281558260018201550155336000526001815260406000208260005281526002604060002060405192815467ffffffffffffffff90818116865260401c169084015273ffffffffffffffffffffffffffffffffffffffff6001820154166040840152015460608201527f82ae5a22c3160d46d62997cfa6f39886b3126a3701c0e42ff3ce4f0b1b6ad0e360803392a3005b3461011557602060031936011261011557600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361011557817f7b49ff2c0000000000000000000000000000000000000000000000000000000060209314908115610f25575b8115610ec8575b5015158152f35b7f6890e5b300000000000000000000000000000000000000000000000000000000811491508115610efb575b5083610ec1565b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610ef4565b610eba565b6080810190811067ffffffffffffffff821117610d5c57604052565b6040810190811067ffffffffffffffff821117610d5c57604052565b6060810190811067ffffffffffffffff821117610d5c57604052565b90601f601f19910116810190811067ffffffffffffffff821117610d5c57604052565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361011557565b919082519283825260005b848110610ff0575050601f19601f8460006020809697860101520116010190565b602081830181015184830182015201610fcf565b67ffffffffffffffff8111610d5c5760051b60200190565b80518210156110305760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea26469706673582212201ab60753767bdd2eb5c5ba93e76e0965697f3f30366dc59ce700907d75ce94fb64736f6c63430008110033

Deployed Bytecode

0x608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a714610e4d5750806319b45c4f14610d8b578063515740a614610b9d578063611efc0914610a9f5780636890e5b3146102ca57806370fe2a261461024657806375d0c0dc146101e85780637b49ff2c14610178578063a0a8e4601461011a5763e8a3d4851461008d57600080fd5b34610115576000600319360112610115576101116040516100ad81610f62565b602f81527f68747470733a2f2f6769746875622e636f6d2f6f75727a6f72612f7a6f72612d60208201527f313135352d636f6e7472616374732f00000000000000000000000000000000006040820152604051918291602083526020830190610fc4565b0390f35b600080fd5b346101155760006003193601126101155761011160405161013a81610f46565b600581527f312e302e300000000000000000000000000000000000000000000000000000006020820152604051918291602083526020830190610fc4565b3461011557606060031936011261011557610191610fa1565b6044359073ffffffffffffffffffffffffffffffffffffffff908183168093036101155716600052600060205260406000206024356000526020526040600020906000526020526020604060002054604051908152f35b346101155760006003193601126101155761011160405161020881610f46565b601981527f4d65726b6c6520547265652053616c65205374726174656779000000000000006020820152604051918291602083526020830190610fc4565b3461011557604060031936011261011557608073ffffffffffffffffffffffffffffffffffffffff80610277610fa1565b166000526001602052604060002060243560005260205260406000206002815492600183015416910154906040519267ffffffffffffffff90818116855260401c16602084015260408301526060820152f35b346101155760a0600319360112610115576102e3610fa1565b5067ffffffffffffffff6084351161011557366023608435011215610115576084356004013567ffffffffffffffff81116101155760843501602481013681116101155760806040519261033684610f46565b606084526000602085015260843590031261011557602460843501359173ffffffffffffffffffffffffffffffffffffffff83168303610115576084803501359067ffffffffffffffff8211610115578260438360843501011215610115576024826084350101356103a781611004565b926103b56040519485610f7e565b8184526020840190819560448460051b836084350101011161011557906044826084350101915b60448460051b826084350101018310610a8a5750505050336000526001602052604060002060243560005260205260406000206040519061041c82610f2a565b600267ffffffffffffffff8254818116855260401c169182602085015273ffffffffffffffffffffffffffffffffffffffff6001820154166040850152015460608301524211610a605767ffffffffffffffff8151164210610a36576060810151946040516104eb816104dd606460843501356044608435013573ffffffffffffffffffffffffffffffffffffffff87166020850160409194939273ffffffffffffffffffffffffffffffffffffffff606083019616825260208201520152565b03601f198101835282610f7e565b60208151910120946000955b85518710156105915761050a878761101c565b5190818110156105805760005260205260406000205b957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461055157600101956104f7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b906000526020526040600020610520565b90878692036109a95750506044608435013561084e575b60646084350135604435818102918183041490151715610551576064350361082457604082015173ffffffffffffffffffffffffffffffffffffffff16158015919061081b5760ff60025b16601f1961061961060383611004565b926106116040519485610f7e565b808452611004565b0160005b8181106107f657505084526040805173ffffffffffffffffffffffffffffffffffffffff90921660208301526024359082015260443560608201526106a09061066981608081016104dd565b6040519061067682610f46565b600282526020820152845160208601519160018301602088015261069a838361101c565b5261101c565b50610782575b50604051602081526060810182519060406020840152815180915260808301602060808360051b86010193019160005b8181106106ed576020870151604087015285850386f35b909192937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80868203018452845190815191600383101561075357610747826040602080959460019782965201519181858201520190610fc4565b960194019291016106d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff60406107ef920151166040519060208201526064356040820152604081526107be81610f62565b604051906107cb82610f46565b600182526020820152825160208401519160018301602086015261069a838361101c565b50816106a6565b60209060405161080581610f46565b600081526060838201528282860101520161061d565b60ff60016105f3565b60046040517f2f4613eb000000000000000000000000000000000000000000000000000000008152fd5b3360005260006020526040600020602435600052602052604060002073ffffffffffffffffffffffffffffffffffffffff82166000526020526040600020805460443581018111610551576044350190553360005260006020526040600020602435600052602052604060002073ffffffffffffffffffffffffffffffffffffffff82166000526020526044608435013560406000205411156105a8573360005260006020526040600020602435600052602052604060002073ffffffffffffffffffffffffffffffffffffffff8216600052602052604060002054906109a56040519283927fe2d9156400000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff6044608435013591166004850160409194939273ffffffffffffffffffffffffffffffffffffffff606083019616825260208201520152565b0390fd5b6060840151604051927fedc7572000000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff6064850195166004850152606060248501525180945260848301916000945b808610610a1e57505082935060448301520390fd5b90926020806001928651815201940195019490610a09565b60046040517fe8c4db82000000000000000000000000000000000000000000000000000000008152fd5b60046040517f0bd8a3eb000000000000000000000000000000000000000000000000000000008152fd5b602080604493853581520193019291506103dc565b3461011557604060031936011261011557610111610abb610fa1565b60006060604051610acb81610f2a565b828152826020820152826040820152015273ffffffffffffffffffffffffffffffffffffffff809116600052600160205260406000206024356000526020526002604060002060405192610b1e84610f2a565b815467ffffffffffffffff90818116865260401c16602085015260018201541660408401520154606082015260405191829182919091606080608083019467ffffffffffffffff808251168552602082015116602085015273ffffffffffffffffffffffffffffffffffffffff60408201511660408501520151910152565b346101155760a06003193601126101155760043560807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601126101155760405167ffffffffffffffff6080820181811183821017610d5c5760405260243581811681036101155782526044358181168103610115576020830190815273ffffffffffffffffffffffffffffffffffffffff9060643582811681036101155760029260408601918252606086019260843584523360005260016020526040600020886000526020526040600020958751167fffffffffffffffffffffffffffffffff000000000000000000000000000000006fffffffffffffffff00000000000000008854935160401b16921617178555600185019151167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055519101557f82ae5a22c3160d46d62997cfa6f39886b3126a3701c0e42ff3ce4f0b1b6ad0e360405180610d57339482919091606080608083019467ffffffffffffffff808251168552602082015116602085015273ffffffffffffffffffffffffffffffffffffffff60408201511660408501520151910152565b0390a3005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b346101155760208060031936011261011557600435903360005260018152604060002082600052815260006002604082208281558260018201550155336000526001815260406000208260005281526002604060002060405192815467ffffffffffffffff90818116865260401c169084015273ffffffffffffffffffffffffffffffffffffffff6001820154166040840152015460608201527f82ae5a22c3160d46d62997cfa6f39886b3126a3701c0e42ff3ce4f0b1b6ad0e360803392a3005b3461011557602060031936011261011557600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361011557817f7b49ff2c0000000000000000000000000000000000000000000000000000000060209314908115610f25575b8115610ec8575b5015158152f35b7f6890e5b300000000000000000000000000000000000000000000000000000000811491508115610efb575b5083610ec1565b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610ef4565b610eba565b6080810190811067ffffffffffffffff821117610d5c57604052565b6040810190811067ffffffffffffffff821117610d5c57604052565b6060810190811067ffffffffffffffff821117610d5c57604052565b90601f601f19910116810190811067ffffffffffffffff821117610d5c57604052565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361011557565b919082519283825260005b848110610ff0575050601f19601f8460006020809697860101520116010190565b602081830181015184830182015201610fcf565b67ffffffffffffffff8111610d5c5760051b60200190565b80518210156110305760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea26469706673582212201ab60753767bdd2eb5c5ba93e76e0965697f3f30366dc59ce700907d75ce94fb64736f6c63430008110033

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  ]

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.