ETH Price: $3,310.66 (-0.99%)
Gas: 1 Gwei

Contract

0xE23142d4757F70dAe18B26e3B4a0E5B1E1b4F6f0
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Unlock Info179297802023-08-16 20:30:11348 days ago1692217811IN
0xE23142d4...1E1b4F6f0
0 ETH0.0020690363.05712308
Set Unlock Info179297322023-08-16 20:20:35348 days ago1692217235IN
0xE23142d4...1E1b4F6f0
0 ETH0.0011350634.59305202
Set Unlock Info179297272023-08-16 20:19:35348 days ago1692217175IN
0xE23142d4...1E1b4F6f0
0 ETH0.0011351434.58502746
Set Unlock Info179297122023-08-16 20:16:35348 days ago1692216995IN
0xE23142d4...1E1b4F6f0
0 ETH0.0013802642.05300967
Set Unlock Info179296862023-08-16 20:11:23348 days ago1692216683IN
0xE23142d4...1E1b4F6f0
0 ETH0.001659950.58828828
Set Unlock Info179221502023-08-15 18:53:11349 days ago1692125591IN
0xE23142d4...1E1b4F6f0
0 ETH0.0015040345.82387785
0x60a06040178699112023-08-08 11:29:11356 days ago1691494151IN
 Create: Lockup
0 ETH0.0127281526.9706562

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Lockup

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 9 : Lockup.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import {ILockup} from "../interfaces/ILockup.sol";
import {MinterAdminCheck} from "../minter/MinterAdminCheck.sol";

/**
 ██████╗██████╗ ███████╗ █████╗  ██████╗ ██████╗ ███████╗
██╔════╝██╔══██╗██╔════╝██╔══██╗██╔═══██╗██╔══██╗██╔════╝
██║     ██████╔╝█████╗  ╚█████╔╝██║   ██║██████╔╝███████╗
██║     ██╔══██╗██╔══╝  ██╔══██╗██║   ██║██╔══██╗╚════██║
╚██████╗██║  ██║███████╗╚█████╔╝╚██████╔╝██║  ██║███████║
 ╚═════╝╚═╝  ╚═╝╚══════╝ ╚════╝  ╚═════╝ ╚═╝  ╚═╝╚══════╝                                                     
 */
contract Lockup is ILockup, MinterAdminCheck {
    /// @notice Lockup information mapping storage
    mapping(address => mapping(uint256 => TokenLockupInfo))
        internal _lockupInfos;

    /// @notice retieves unlock date for token
    /// @param _target contract target
    /// @param _tokenId tokenId to retrieve unlock date
    function unlockInfo(
        address _target,
        uint256 _tokenId
    ) public view returns (TokenLockupInfo memory info) {
        info = _lockupInfos[_target][_tokenId];
    }

    /// @notice retrieves locked state for token
    /// @param _target contract target
    /// @param _tokenId tokenId to retrieve lock state
    function isLocked(
        address _target,
        uint256 _tokenId
    ) external view returns (bool) {
        return block.timestamp < unlockInfo(_target, _tokenId).unlockDate;
    }

    /// @notice sets unlock tier for token
    /// @param _target target contract
    /// @param _tokenId tokenId to set unlock date for
    /// @param _unlockData unlock information
    function setUnlockInfo(
        address _target,
        uint256 _tokenId,
        bytes memory _unlockData
    ) external onlyMinterOrAdmin(_target) {
        _setUnlockInfo(_target, _tokenId, _unlockData);
    }

    /// @notice unlocks token
    /// @param _target target contract
    /// @param _tokenId tokenId to unlock
    function unlock(address _target, uint256 _tokenId) private {
        uint64 newUnlockDate = uint64(block.timestamp);
        bytes memory data = abi.encode(newUnlockDate, 0);
        _setUnlockInfo(_target, _tokenId, data);
    }

    /// @notice sets unlock tier for token
    /// @param _target target contract
    /// @param _tokenId tokenId to set unlock date for
    /// @param _unlockData unlock information
    function _setUnlockInfo(
        address _target,
        uint256 _tokenId,
        bytes memory _unlockData
    ) private {
        // data format: uint64 unlockDate, uint256 priceToUnlock
        (uint64 _unlockDate, uint256 _priceToUnlock) = abi.decode(
            _unlockData,
            (uint64, uint256)
        );
        _lockupInfos[_target][_tokenId] = TokenLockupInfo({
            unlockDate: _unlockDate,
            priceToUnlock: _priceToUnlock
        });

        emit TokenLockupUpdated({
            target: _target,
            tokenId: _tokenId,
            unlockDate: _unlockDate,
            priceToUnlock: _priceToUnlock
        });
    }

    /// @notice pay to unlock a locked token
    /// @param _target target contract
    /// @param _tokenId tokenId to unlock
    function payToUnlock(
        address payable _target,
        uint256 _tokenId
    ) public payable {
        // verify paid unlock price
        uint256 priceToPay = _lockupInfos[_target][_tokenId].priceToUnlock;
        if (msg.value < priceToPay) {
            revert Unlock_WrongPrice(priceToPay);
        }

        // unlock token
        unlock(_target, _tokenId);

        // send funds to the target
        (bool success, ) = _target.call{value: priceToPay}("");
        require(success, "Transfer failed.");

        // if the payment is more than the unlock price, refund the extra
        if (msg.value > priceToPay) {
            uint256 refundAmount = msg.value - priceToPay;
            (bool refundSuccess, ) = msg.sender.call{value: refundAmount}("");
            require(refundSuccess, "Refund failed.");
        }
    }
}

File 2 of 9 : IERC721A.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

/**
 * @dev Interface of ERC721A.
 */
interface IERC721A {
    /**
     * The caller must own the token or be an approved operator.
     */
    error ApprovalCallerNotOwnerNorApproved();

    /**
     * The token does not exist.
     */
    error ApprovalQueryForNonexistentToken();

    /**
     * Cannot query the balance for the zero address.
     */
    error BalanceQueryForZeroAddress();

    /**
     * Cannot mint to the zero address.
     */
    error MintToZeroAddress();

    /**
     * The quantity of tokens minted must be more than zero.
     */
    error MintZeroQuantity();

    /**
     * The token does not exist.
     */
    error OwnerQueryForNonexistentToken();

    /**
     * The caller must own the token or be an approved operator.
     */
    error TransferCallerNotOwnerNorApproved();

    /**
     * The token must be owned by `from`.
     */
    error TransferFromIncorrectOwner();

    /**
     * Cannot safely transfer to a contract that does not implement the
     * ERC721Receiver interface.
     */
    error TransferToNonERC721ReceiverImplementer();

    /**
     * Cannot transfer to the zero address.
     */
    error TransferToZeroAddress();

    /**
     * The token does not exist.
     */
    error URIQueryForNonexistentToken();

    /**
     * The `quantity` minted with ERC2309 exceeds the safety limit.
     */
    error MintERC2309QuantityExceedsLimit();

    /**
     * The `extraData` cannot be set on an unintialized ownership slot.
     */
    error OwnershipNotInitializedForExtraData();

    // =============================================================
    //                            STRUCTS
    // =============================================================

    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Stores the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
        // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
        uint24 extraData;
    }

    // =============================================================
    //                         TOKEN COUNTERS
    // =============================================================

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() external view returns (uint256);

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);

    // =============================================================
    //                            IERC721
    // =============================================================

    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

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

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

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

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

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

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom}
     * whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

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

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

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

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

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);

    // =============================================================
    //                           IERC2309
    // =============================================================

    /**
     * @dev Emitted when tokens in `fromTokenId` to `toTokenId`
     * (inclusive) is transferred from `from` to `to`, as defined in the
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
     *
     * See {_mintERC2309} for more details.
     */
    event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}

File 3 of 9 : ICre8ing.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import {ILockup} from "./ILockup.sol";

interface ICre8ing {
    /// @notice Getter for Lockup interface
    function lockUp(address) external view returns (ILockup);

    /// @dev Emitted when a CRE8OR begins cre8ing.
    event Cre8ed(address, uint256 indexed tokenId);

    /// @dev Emitted when a CRE8OR stops cre8ing; either through standard means or
    ///     by expulsion.
    event Uncre8ed(address, uint256 indexed tokenId);

    /// @dev Emitted when a CRE8OR is expelled from the Warehouse.
    event Expelled(address, uint256 indexed tokenId);

    /// @notice Missing cre8ing status
    error CRE8ING_NotCre8ing(address, uint256 tokenId);

    /// @notice Cre8ing Closed
    error Cre8ing_Cre8ingClosed();

    /// @notice Cre8ing
    error Cre8ing_Cre8ing();

    /// @notice Missing Lockup
    error Cre8ing_MissingLockup();

    /// @notice Cre8ing period
    function cre8ingPeriod(
        address,
        uint256
    ) external view returns (bool cre8ing, uint256 current, uint256 total);

    /// @notice open / close staking
    function setCre8ingOpen(address, bool) external;

    /// @notice force removal from staking
    function expelFromWarehouse(address, uint256) external;

    /// @notice function getCre8ingStarted(
    function getCre8ingStarted(
        address _target,
        uint256 tokenId
    ) external view returns (uint256);

    /// @notice array of staked tokenIDs
    /// @dev used in cre8ors ui to quickly get list of staked NFTs.
    function cre8ingTokens(
        address _target
    ) external view returns (uint256[] memory stakedTokens);

    /// @notice initialize both staking and lockups
    function inializeStakingAndLockup(
        address _target,
        uint256[] memory,
        bytes memory
    ) external;

    /// @notice Set a new lockup for the target.
    /// @param _target The target address.
    /// @param newLockup The new lockup contract address.
    function setLockup(address _target, ILockup newLockup) external;
}

File 4 of 9 : ICre8ors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import {IERC721Drop} from "./IERC721Drop.sol";
import {ILockup} from "./ILockup.sol";
import {IERC721A} from "erc721a/contracts/IERC721A.sol";
import {ICre8ing} from "./ICre8ing.sol";
import {ISubscription} from "../subscription/interfaces/ISubscription.sol";

/**
 ██████╗██████╗ ███████╗ █████╗  ██████╗ ██████╗ ███████╗
██╔════╝██╔══██╗██╔════╝██╔══██╗██╔═══██╗██╔══██╗██╔════╝
██║     ██████╔╝█████╗  ╚█████╔╝██║   ██║██████╔╝███████╗
██║     ██╔══██╗██╔══╝  ██╔══██╗██║   ██║██╔══██╗╚════██║
╚██████╗██║  ██║███████╗╚█████╔╝╚██████╔╝██║  ██║███████║
 ╚═════╝╚═╝  ╚═╝╚══════╝ ╚════╝  ╚═════╝ ╚═╝  ╚═╝╚══════╝                                                       
*/
/// @notice Interface for Cre8ors Drops contract
interface ICre8ors is IERC721Drop, IERC721A {
    function cre8ing() external view returns (ICre8ing);

    /// @notice Getter for last minted token ID (gets next token id and subtracts 1)
    function _lastMintedTokenId() external view returns (uint256);

    /// @dev Returns `true` if `account` has been granted `role`.
    function hasRole(
        bytes32 role,
        address account
    ) external view returns (bool);

    function subscription() external view returns (address);

    function setSubscription(address newSubscription) external;

    function setCre8ing(ICre8ing _cre8ing) external;

    function MINTER_ROLE() external returns (bytes32);
}

File 5 of 9 : IERC721Drop.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

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

/**
 ██████╗██████╗ ███████╗ █████╗  ██████╗ ██████╗ ███████╗
██╔════╝██╔══██╗██╔════╝██╔══██╗██╔═══██╗██╔══██╗██╔════╝
██║     ██████╔╝█████╗  ╚█████╔╝██║   ██║██████╔╝███████╗
██║     ██╔══██╗██╔══╝  ██╔══██╗██║   ██║██╔══██╗╚════██║
╚██████╗██║  ██║███████╗╚█████╔╝╚██████╔╝██║  ██║███████║
 ╚═════╝╚═╝  ╚═╝╚══════╝ ╚════╝  ╚═════╝ ╚═╝  ╚═╝╚══════╝                                                       
*/
/// @notice Interface for Cre8ors Drop contract
interface IERC721Drop {
    // Access errors

    /// @notice Only admin can access this function
    error Access_OnlyAdmin();
    /// @notice Missing the given role or admin access
    error Access_MissingRoleOrAdmin(bytes32 role);
    /// @notice Withdraw is not allowed by this user
    error Access_WithdrawNotAllowed();
    /// @notice Cannot withdraw funds due to ETH send failure.
    error Withdraw_FundsSendFailure();
    /// @notice Missing the owner role.
    error Access_OnlyOwner();
    /// @notice Missing the owner role or approved nft access.
    error Access_MissingOwnerOrApproved();

    // Sale/Purchase errors
    /// @notice Sale is inactive
    error Sale_Inactive();
    /// @notice Presale is inactive
    error Presale_Inactive();
    /// @notice Presale merkle root is invalid
    error Presale_MerkleNotApproved();
    /// @notice Wrong price for purchase
    error Purchase_WrongPrice(uint256 correctPrice);
    /// @notice NFT sold out
    error Mint_SoldOut();
    /// @notice Too many purchase for address
    error Purchase_TooManyForAddress();
    /// @notice Too many presale for address
    error Presale_TooManyForAddress();

    // Admin errors
    /// @notice Royalty percentage too high
    error Setup_RoyaltyPercentageTooHigh(uint16 maxRoyaltyBPS);
    /// @notice Invalid admin upgrade address
    error Admin_InvalidUpgradeAddress(address proposedAddress);
    /// @notice Unable to finalize an edition not marked as open (size set to uint64_max_value)
    error Admin_UnableToFinalizeNotOpenEdition();

    /// @notice Event emitted for each sale
    /// @param to address sale was made to
    /// @param quantity quantity of the minted nfts
    /// @param pricePerToken price for each token
    /// @param firstPurchasedTokenId first purchased token ID (to get range add to quantity for max)
    event Sale(
        address indexed to,
        uint256 indexed quantity,
        uint256 indexed pricePerToken,
        uint256 firstPurchasedTokenId
    );

    /// @notice Sales configuration has been changed
    /// @dev To access new sales configuration, use getter function.
    /// @param changedBy Changed by user
    event SalesConfigChanged(address indexed changedBy);

    /// @notice Event emitted when the funds recipient is changed
    /// @param newAddress new address for the funds recipient
    /// @param changedBy address that the recipient is changed by
    event FundsRecipientChanged(
        address indexed newAddress,
        address indexed changedBy
    );

    /// @notice Event emitted when the funds are withdrawn from the minting contract
    /// @param withdrawnBy address that issued the withdraw
    /// @param withdrawnTo address that the funds were withdrawn to
    /// @param amount amount that was withdrawn
    event FundsWithdrawn(
        address indexed withdrawnBy,
        address indexed withdrawnTo,
        uint256 amount
    );

    /// @notice Event emitted when an open mint is finalized and further minting is closed forever on the contract.
    /// @param sender address sending close mint
    /// @param numberOfMints number of mints the contract is finalized at
    event OpenMintFinalized(address indexed sender, uint256 numberOfMints);

    /// @notice Event emitted when metadata renderer is updated.
    /// @param sender address of the updater
    /// @param renderer new metadata renderer address
    event UpdatedMetadataRenderer(address sender, IMetadataRenderer renderer);

    /// @notice General configuration for NFT Minting and bookkeeping
    struct Configuration {
        /// @dev Metadata renderer (uint160)
        IMetadataRenderer metadataRenderer;
        /// @dev Total size of edition that can be minted (uint160+64 = 224)
        uint64 editionSize;
        /// @dev Royalty amount in bps (uint224+16 = 240)
        uint16 royaltyBPS;
        /// @dev Funds recipient for sale (new slot, uint160)
        address payable fundsRecipient;
    }

    /// @notice Sales states and configuration
    /// @dev Uses 3 storage slots
    struct SalesConfiguration {
        /// @dev Public sale price (max ether value > 1000 ether with this value)
        uint104 publicSalePrice;
        /// @dev ERC20 Token
        address erc20PaymentToken;
        /// @notice Purchase mint limit per address (if set to 0 === unlimited mints)
        /// @dev Max purchase number per txn (90+32 = 122)
        uint32 maxSalePurchasePerAddress;
        /// @dev uint64 type allows for dates into 292 billion years
        /// @notice Public sale start timestamp (136+64 = 186)
        uint64 publicSaleStart;
        /// @notice Public sale end timestamp (186+64 = 250)
        uint64 publicSaleEnd;
        /// @notice Presale start timestamp
        /// @dev new storage slot
        uint64 presaleStart;
        /// @notice Presale end timestamp
        uint64 presaleEnd;
        /// @notice Presale merkle root
        bytes32 presaleMerkleRoot;
    }

    /// @notice CRE8ORS - General configuration for Builder Rewards burn requirements
    struct BurnConfiguration {
        /// @dev Token to burn
        address burnToken;
        /// @dev Required number of tokens to burn
        uint256 burnQuantity;
    }

    /// @notice Sales states and configuration
    /// @dev Uses 3 storage slots
    struct ERC20SalesConfiguration {
        /// @notice Public sale price
        /// @dev max ether value > 1000 ether with this value
        uint104 publicSalePrice;
        /// @dev ERC20 Token
        address erc20PaymentToken;
        /// @notice Purchase mint limit per address (if set to 0 === unlimited mints)
        /// @dev Max purchase number per txn (90+32 = 122)
        uint32 maxSalePurchasePerAddress;
        /// @dev uint64 type allows for dates into 292 billion years
        /// @notice Public sale start timestamp (136+64 = 186)
        uint64 publicSaleStart;
        /// @notice Public sale end timestamp (186+64 = 250)
        uint64 publicSaleEnd;
        /// @notice Presale start timestamp
        /// @dev new storage slot
        uint64 presaleStart;
        /// @notice Presale end timestamp
        uint64 presaleEnd;
        /// @notice Presale merkle root
        bytes32 presaleMerkleRoot;
    }

    /// @notice Return value for sales details to use with front-ends
    struct SaleDetails {
        // Synthesized status variables for sale and presale
        bool publicSaleActive;
        bool presaleActive;
        // Price for public sale
        uint256 publicSalePrice;
        // Timed sale actions for public sale
        uint64 publicSaleStart;
        uint64 publicSaleEnd;
        // Timed sale actions for presale
        uint64 presaleStart;
        uint64 presaleEnd;
        // Merkle root (includes address, quantity, and price data for each entry)
        bytes32 presaleMerkleRoot;
        // Limit public sale to a specific number of mints per wallet
        uint256 maxSalePurchasePerAddress;
        // Information about the rest of the supply
        // Total that have been minted
        uint256 totalMinted;
        // The total supply available
        uint256 maxSupply;
    }

    /// @notice Return value for sales details to use with front-ends
    struct ERC20SaleDetails {
        /// @notice Synthesized status variables for sale
        bool publicSaleActive;
        /// @notice Synthesized status variables for presale
        bool presaleActive;
        /// @notice Price for public sale
        uint256 publicSalePrice;
        /// @notice ERC20 contract address for payment. address(0) for ETH.
        address erc20PaymentToken;
        /// @notice public sale start
        uint64 publicSaleStart;
        /// @notice public sale end
        uint64 publicSaleEnd;
        /// @notice Timed sale actions for presale start
        uint64 presaleStart;
        /// @notice Timed sale actions for presale end
        uint64 presaleEnd;
        /// @notice Merkle root (includes address, quantity, and price data for each entry)
        bytes32 presaleMerkleRoot;
        /// @notice Limit public sale to a specific number of mints per wallet
        uint256 maxSalePurchasePerAddress;
        /// @notice Total that have been minted
        uint256 totalMinted;
        /// @notice The total supply available
        uint256 maxSupply;
    }

    /// @notice Return type of specific mint counts and details per address
    struct AddressMintDetails {
        /// Number of total mints from the given address
        uint256 totalMints;
        /// Number of presale mints from the given address
        uint256 presaleMints;
        /// Number of public mints from the given address
        uint256 publicMints;
    }

    /// @notice External purchase function (payable in eth)
    /// @param quantity to purchase
    /// @return first minted token ID
    function purchase(uint256 quantity) external payable returns (uint256);

    /// @notice External purchase presale function (takes a merkle proof and matches to root) (payable in eth)
    /// @param quantity to purchase
    /// @param maxQuantity can purchase (verified by merkle root)
    /// @param pricePerToken price per token allowed (verified by merkle root)
    /// @param merkleProof input for merkle proof leaf verified by merkle root
    /// @return first minted token ID
    function purchasePresale(
        uint256 quantity,
        uint256 maxQuantity,
        uint256 pricePerToken,
        bytes32[] memory merkleProof
    ) external payable returns (uint256);

    /// @notice Function to return the global sales details for the given drop
    function saleDetails() external view returns (ERC20SaleDetails memory);

    /// @notice Function to return the specific sales details for a given address
    /// @param minter address for minter to return mint information for
    function mintedPerAddress(
        address minter
    ) external view returns (AddressMintDetails memory);

    /// @notice This is the opensea/public owner setting that can be set by the contract admin
    function owner() external view returns (address);

    /// @notice Update the metadata renderer
    /// @param newRenderer new address for renderer
    /// @param setupRenderer data to call to bootstrap data for the new renderer (optional)
    function setMetadataRenderer(
        IMetadataRenderer newRenderer,
        bytes memory setupRenderer
    ) external;

    /// @notice This is an admin mint function to mint a quantity to a specific address
    /// @param to address to mint to
    /// @param quantity quantity to mint
    /// @return the id of the first minted NFT
    function adminMint(address to, uint256 quantity) external returns (uint256);

    /// @notice This is an admin mint function to mint a single nft each to a list of addresses
    /// @param to list of addresses to mint an NFT each to
    /// @return the id of the first minted NFT
    function adminMintAirdrop(address[] memory to) external returns (uint256);

    /// @dev Getter for admin role associated with the contract to handle metadata
    /// @return boolean if address is admin
    function isAdmin(address user) external view returns (bool);
}

File 6 of 9 : ILockup.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

/**
 ██████╗██████╗ ███████╗ █████╗  ██████╗ ██████╗ ███████╗
██╔════╝██╔══██╗██╔════╝██╔══██╗██╔═══██╗██╔══██╗██╔════╝
██║     ██████╔╝█████╗  ╚█████╔╝██║   ██║██████╔╝███████╗
██║     ██╔══██╗██╔══╝  ██╔══██╗██║   ██║██╔══██╗╚════██║
╚██████╗██║  ██║███████╗╚█████╔╝╚██████╔╝██║  ██║███████║
 ╚═════╝╚═╝  ╚═╝╚══════╝ ╚════╝  ╚═════╝ ╚═╝  ╚═╝╚══════╝                                                     
 */
interface ILockup {
    /// @notice Storage for token edition information
    struct TokenLockupInfo {
        uint64 unlockDate;
        uint256 priceToUnlock;
    }

    /// @notice Locked
    error Lockup_Locked();

    /// @notice Wrong price for unlock
    error Unlock_WrongPrice(uint256 correctPrice);

    /// @notice Event for updated Lockup
    event TokenLockupUpdated(
        address indexed target,
        uint256 tokenId,
        uint64 unlockDate,
        uint256 priceToUnlock
    );

    /// @notice retrieves locked state for token
    function isLocked(address, uint256) external view returns (bool);

    /// @notice retieves unlock date for token
    function unlockInfo(
        address,
        uint256
    ) external view returns (TokenLockupInfo memory);

    /// @notice sets unlock tier for token
    function setUnlockInfo(address, uint256, bytes memory) external;

    /// @notice pay to unlock a locked token
    function payToUnlock(address payable, uint256) external payable;
}

File 7 of 9 : IMetadataRenderer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

/**
 ██████╗██████╗ ███████╗ █████╗  ██████╗ ██████╗ ███████╗
██╔════╝██╔══██╗██╔════╝██╔══██╗██╔═══██╗██╔══██╗██╔════╝
██║     ██████╔╝█████╗  ╚█████╔╝██║   ██║██████╔╝███████╗
██║     ██╔══██╗██╔══╝  ██╔══██╗██║   ██║██╔══██╗╚════██║
╚██████╗██║  ██║███████╗╚█████╔╝╚██████╔╝██║  ██║███████║
 ╚═════╝╚═╝  ╚═╝╚══════╝ ╚════╝  ╚═════╝ ╚═╝  ╚═╝╚══════╝                                                     
 */

/// @dev credit: https://github.com/ourzora/zora-drops-contracts
interface IMetadataRenderer {
    function tokenURI(uint256) external view returns (string memory);

    function contractURI() external view returns (string memory);

    function initializeWithData(bytes memory initData) external;
}

File 8 of 9 : MinterAdminCheck.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

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

contract MinterAdminCheck {
    /// @notice Access control roles
    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
    bytes32 public immutable MINTER_ROLE = keccak256("MINTER");

    /// @notice Missing the minter role or admin access
    error AdminAccess_MissingMinterOrAdmin();

    /// @notice Modifier to require the sender to be an admin
    /// @param target address that the user wants to modify
    modifier onlyMinterOrAdmin(address target) {
        if (
            target != msg.sender &&
            !ICre8ors(target).hasRole(DEFAULT_ADMIN_ROLE, msg.sender) &&
            !ICre8ors(target).hasRole(MINTER_ROLE, msg.sender)
        ) {
            revert AdminAccess_MissingMinterOrAdmin();
        }

        _;
    }
}

File 9 of 9 : ISubscription.sol
/// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

/// @title ISubscription
/// @dev Interface for managing subscriptions to NFTs.
interface ISubscription {
    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    /// @notice The subscription associated with the provided token ID is invalid or has expired.
    error InvalidSubscription();

    /// @notice Attempting to set a subscription contract address with a zero address value.
    error SubscriptionCannotBeZeroAddress();

    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    /// @dev Emitted when the renewability status of subscriptions is updated.
    event RenewableUpdate(bool renewable);

    /// @dev Emitted when the minimum duration for subscription renewal is updated.
    event MinRenewalDurationUpdate(uint64 duration);

    /// @dev Emitted when the maximum duration for subscription renewal is updated.
    event MaxRenewalDurationUpdate(uint64 duration);

    /*//////////////////////////////////////////////////////////////
                           CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Checks the subscription for the given `tokenId`.
    /// Throws if `tokenId` subscription has expired.
    /// @param tokenId The unique identifier of the NFT token.
    function checkSubscription(uint256 tokenId) external view;

    /// @notice Returns whether the subscription for the given `tokenId` is valid.
    /// @param tokenId The unique identifier of the NFT token.
    /// @return A boolean indicating if the subscription is valid.
    function isSubscriptionValid(uint256 tokenId) external view returns (bool);

    /*//////////////////////////////////////////////////////////////
                         NON-CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /*//////////   updateSubscriptionForFree variants   //////////*/

    /// @notice Extends the subscription for the given `tokenId` with a specified `duration` for free.
    /// @dev This function is meant to be called by the minter when minting the NFT to subscribe.
    /// @param target The address of the contract implementing the access control
    /// @param duration The duration (in seconds) to extend the subscription for.
    /// @param tokenId The unique identifier of the NFT token to be subscribed.
    function updateSubscriptionForFree(address target, uint64 duration, uint256 tokenId) external;

    /// @notice Extends the subscription for the given `tokenIds` with a specified `duration` for free.
    /// @dev This function is meant to be called by the minter when minting the NFT to subscribe.
    /// @param target The address of the contract implementing the access control
    /// @param duration The duration (in seconds) to extend the subscription for.
    /// @param tokenIds An array of unique identifiers of the NFT tokens to update the subscriptions for.
    function updateSubscriptionForFree(address target, uint64 duration, uint256[] calldata tokenIds) external;

    /*//////////////   updateSubscription variants   /////////////*/

    /// @notice Extends the subscription for the given `tokenId` with a specified `duration`, using native currency as
    /// payment.
    /// @dev This function is meant to be called by the minter when minting the NFT to subscribe.
    /// @param target The address of the contract implementing the access control
    /// @param duration The duration (in seconds) to extend the subscription for.
    /// @param tokenId The unique identifier of the NFT token to be subscribed.
    function updateSubscription(address target, uint64 duration, uint256 tokenId) external payable;

    /// @notice Extends the subscription for the given `tokenIds` with a specified `duration`, using native currency as
    /// payment.
    /// @dev This function is meant to be called by the minter when minting the NFT to subscribe.
    /// @param target The address of the contract implementing the access control
    /// @param duration The duration (in seconds) to extend the subscription for.
    /// @param tokenIds An array of unique identifiers of the NFT tokens to update the subscriptions for.
    function updateSubscription(address target, uint64 duration, uint256[] calldata tokenIds) external payable;
}

Settings
{
  "remappings": [
    "@openzeppelin/=lib/openzeppelin-contracts/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "ERC6551/=lib/ERC6551/src/",
    "ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/",
    "ERC721A/=lib/ERC721A/contracts/",
    "ERC721C/=lib/creator-token-contracts/contracts/",
    "ERC721H/=lib/ERC721H/src/",
    "account-abstraction/=lib/account-abstraction/contracts/",
    "creator-token-contracts/=lib/creator-token-contracts/contracts/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "erc6551/=lib/tokenbound/lib/reference/src/",
    "erc721a/=lib/ERC721A/",
    "forge-std/=lib/forge-std/src/",
    "hardhat/=lib/creator-token-contracts/node_modules/hardhat/",
    "murky/=lib/creator-token-contracts/lib/murky/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
    "reference/=lib/tokenbound/lib/reference/src/",
    "sstore2/=lib/ERC6551/lib/sstore2/contracts/",
    "tokenbound/=lib/tokenbound/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"name":"AdminAccess_MissingMinterOrAdmin","type":"error"},{"inputs":[],"name":"Lockup_Locked","type":"error"},{"inputs":[{"internalType":"uint256","name":"correctPrice","type":"uint256"}],"name":"Unlock_WrongPrice","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"unlockDate","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"priceToUnlock","type":"uint256"}],"name":"TokenLockupUpdated","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"isLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_target","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"payToUnlock","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_unlockData","type":"bytes"}],"name":"setUnlockInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"unlockInfo","outputs":[{"components":[{"internalType":"uint64","name":"unlockDate","type":"uint64"},{"internalType":"uint256","name":"priceToUnlock","type":"uint256"}],"internalType":"struct ILockup.TokenLockupInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"}]

60a06040527ff0887ba65ee2024ea881d91b74c2450ef19e1557f03bed3ea9f16b037cbe2dc960805234801561003457600080fd5b506080516107926100576000396000818161013e01526101fc01526107926000f3fe6080604052600436106100555760003560e01c8063188182401461005a57806319819e361461007c57806319c60a90146100c657806399cca36c146100d9578063a217fddf14610109578063d53913931461012c575b600080fd5b34801561006657600080fd5b5061007a6100753660046105da565b610160565b005b34801561008857600080fd5b5061009c6100973660046106a7565b6102ac565b60408051825167ffffffffffffffff16815260209283015192810192909252015b60405180910390f35b61007a6100d43660046106a7565b610301565b3480156100e557600080fd5b506100f96100f43660046106a7565b610496565b60405190151581526020016100bd565b34801561011557600080fd5b5061011e600081565b6040519081526020016100bd565b34801561013857600080fd5b5061011e7f000000000000000000000000000000000000000000000000000000000000000081565b826001600160a01b03811633148015906101e65750604051632474521560e21b8152600060048201523360248201526001600160a01b038216906391d1485490604401602060405180830381865afa1580156101c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e491906106d3565b155b801561027d5750604051632474521560e21b81527f000000000000000000000000000000000000000000000000000000000000000060048201523360248201526001600160a01b038216906391d1485490604401602060405180830381865afa158015610257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027b91906106d3565b155b1561029b57604051630c198a4f60e01b815260040160405180910390fd5b6102a68484846104b6565b50505050565b604080518082018252600080825260209182018190526001600160a01b03949094168452838152818420928452918252918290208251808401909352805467ffffffffffffffff168352600101549082015290565b6001600160a01b0382166000908152602081815260408083208484529091529020600101543481111561034e5760405162631da360e01b8152600481018290526024015b60405180910390fd5b6103588383610575565b6000836001600160a01b03168260405160006040518083038185875af1925050503d80600081146103a5576040519150601f19603f3d011682016040523d82523d6000602084013e6103aa565b606091505b50509050806103ee5760405162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b6044820152606401610345565b813411156102a657600061040283346106fc565b604051909150600090339083908381818185875af1925050503d8060008114610447576040519150601f19603f3d011682016040523d82523d6000602084013e61044c565b606091505b505090508061048e5760405162461bcd60e51b815260206004820152600e60248201526d2932b33ab732103330b4b632b21760911b6044820152606401610345565b505050505050565b60006104a283836102ac565b5167ffffffffffffffff1642109392505050565b600080828060200190518101906104cd9190610721565b60408051808201825267ffffffffffffffff84811680835260208084018681526001600160a01b038d1660008181528084528781208e825284528790209551865467ffffffffffffffff191695169490941785555160019094019390935583518a815292830152918101839052929450909250907f47981547d471be4ec5bf24053e49c4ebb8ea91d6026c25490ee042d85d9fafc99060600160405180910390a25050505050565b604080514267ffffffffffffffff8116602083015260008284015282518083038401815260609092019092526102a68484836104b6565b6001600160a01b03811681146105c157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b6000806000606084860312156105ef57600080fd5b83356105fa816105ac565b925060208401359150604084013567ffffffffffffffff8082111561061e57600080fd5b818601915086601f83011261063257600080fd5b813581811115610644576106446105c4565b604051601f8201601f19908116603f0116810190838211818310171561066c5761066c6105c4565b8160405282815289602084870101111561068557600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b600080604083850312156106ba57600080fd5b82356106c5816105ac565b946020939093013593505050565b6000602082840312156106e557600080fd5b815180151581146106f557600080fd5b9392505050565b60008282101561071c57634e487b7160e01b600052601160045260246000fd5b500390565b6000806040838503121561073457600080fd5b825167ffffffffffffffff8116811461074c57600080fd5b602093909301519294929350505056fea26469706673582212200ab2981c1c9c8d9a620bc0db34d0e8b0ee512495ed4bff159d17094590d70c8264736f6c634300080f0033

Deployed Bytecode

0x6080604052600436106100555760003560e01c8063188182401461005a57806319819e361461007c57806319c60a90146100c657806399cca36c146100d9578063a217fddf14610109578063d53913931461012c575b600080fd5b34801561006657600080fd5b5061007a6100753660046105da565b610160565b005b34801561008857600080fd5b5061009c6100973660046106a7565b6102ac565b60408051825167ffffffffffffffff16815260209283015192810192909252015b60405180910390f35b61007a6100d43660046106a7565b610301565b3480156100e557600080fd5b506100f96100f43660046106a7565b610496565b60405190151581526020016100bd565b34801561011557600080fd5b5061011e600081565b6040519081526020016100bd565b34801561013857600080fd5b5061011e7ff0887ba65ee2024ea881d91b74c2450ef19e1557f03bed3ea9f16b037cbe2dc981565b826001600160a01b03811633148015906101e65750604051632474521560e21b8152600060048201523360248201526001600160a01b038216906391d1485490604401602060405180830381865afa1580156101c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e491906106d3565b155b801561027d5750604051632474521560e21b81527ff0887ba65ee2024ea881d91b74c2450ef19e1557f03bed3ea9f16b037cbe2dc960048201523360248201526001600160a01b038216906391d1485490604401602060405180830381865afa158015610257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027b91906106d3565b155b1561029b57604051630c198a4f60e01b815260040160405180910390fd5b6102a68484846104b6565b50505050565b604080518082018252600080825260209182018190526001600160a01b03949094168452838152818420928452918252918290208251808401909352805467ffffffffffffffff168352600101549082015290565b6001600160a01b0382166000908152602081815260408083208484529091529020600101543481111561034e5760405162631da360e01b8152600481018290526024015b60405180910390fd5b6103588383610575565b6000836001600160a01b03168260405160006040518083038185875af1925050503d80600081146103a5576040519150601f19603f3d011682016040523d82523d6000602084013e6103aa565b606091505b50509050806103ee5760405162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b6044820152606401610345565b813411156102a657600061040283346106fc565b604051909150600090339083908381818185875af1925050503d8060008114610447576040519150601f19603f3d011682016040523d82523d6000602084013e61044c565b606091505b505090508061048e5760405162461bcd60e51b815260206004820152600e60248201526d2932b33ab732103330b4b632b21760911b6044820152606401610345565b505050505050565b60006104a283836102ac565b5167ffffffffffffffff1642109392505050565b600080828060200190518101906104cd9190610721565b60408051808201825267ffffffffffffffff84811680835260208084018681526001600160a01b038d1660008181528084528781208e825284528790209551865467ffffffffffffffff191695169490941785555160019094019390935583518a815292830152918101839052929450909250907f47981547d471be4ec5bf24053e49c4ebb8ea91d6026c25490ee042d85d9fafc99060600160405180910390a25050505050565b604080514267ffffffffffffffff8116602083015260008284015282518083038401815260609092019092526102a68484836104b6565b6001600160a01b03811681146105c157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b6000806000606084860312156105ef57600080fd5b83356105fa816105ac565b925060208401359150604084013567ffffffffffffffff8082111561061e57600080fd5b818601915086601f83011261063257600080fd5b813581811115610644576106446105c4565b604051601f8201601f19908116603f0116810190838211818310171561066c5761066c6105c4565b8160405282815289602084870101111561068557600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b600080604083850312156106ba57600080fd5b82356106c5816105ac565b946020939093013593505050565b6000602082840312156106e557600080fd5b815180151581146106f557600080fd5b9392505050565b60008282101561071c57634e487b7160e01b600052601160045260246000fd5b500390565b6000806040838503121561073457600080fd5b825167ffffffffffffffff8116811461074c57600080fd5b602093909301519294929350505056fea26469706673582212200ab2981c1c9c8d9a620bc0db34d0e8b0ee512495ed4bff159d17094590d70c8264736f6c634300080f0033

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.