ERC721Generative

Overview

The ERC721Generative contract enables the creation of generative NFTs, where the art associated with each NFT is dynamically generated based on a script stored on-chain. ERC721Generative integrates generative art capabilities into the ERC-721 token framework. It uses a script, stored via the SSTORE2 library, to generate NFT content dynamically. This approach allows for efficient storage and execution of complex generative algorithms directly on Ethereum.

Media API

Provides a static snapshot of the rendered live-view for a given Ninfa token. Assets are not saved on IPFS or other cloud storage as each image is generated directly from the code stored on generative smart contracts.

Mainnet

Pattern
Sample

https://generator.ninfa.io/{contractAddress}/{tokenID}.png

When a user hits this endpoint, the server will generate the art for the corresponding NFT token ID.

Usage

The contract contains a scriptStorageAddress variable to store the logic to generate the art for a given NFT, which gets set in the constructor (when the contract gets deployed).

// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import "../extensions/ERC721Enumerable.sol";
import "../extensions/ERC721Metadata_URI_autoIncrementID.sol";
import "../extensions/ERC721Royalty.sol";
import "../extensions/ERC721Burnable.sol";
import "access/Owned.sol";
import "utils/Address.sol";
import "utils/cryptography/MerkleProofLib.sol";
import "utils/cryptography/SSTORE2.sol";

contract ERC721Generative is
    Owned,
    ERC721Burnable,
    ERC721Royalty,
    ERC721Metadata_URI_autoIncrementID,
    ERC721Enumerable
{
    address public scriptStorageAddress; // Address of the deployed contract containing the script

    function setScript(bytes calldata _script) external onlyBeforeDropStart onlyOwner {
        scriptStorageAddress = SSTORE2.write(_script);
    }
    
    function getScript() external view returns (string memory) {
        return string(SSTORE2.read(scriptStorageAddress));
    }
    
    function initialize(bytes calldata _data) external {
        require(msg.sender == FACTORY);
        bytes memory _script;
        string memory baseURI_;
        (
            _name,
            symbol,
            baseURI_,
            merkleRoot,
            dropTime,
            ALPrice,
            publicPrice,
            dropDurationAL,
            dropDurationPublic,
            maxSupply,
            feeAmount,
            feeRecipient,
            _script
        ) = abi.decode(
            _data,
            (
                string,
                string,
                string,
                bytes32,
                uint256,
                uint256,
                uint256,
                uint256,
                uint256,
                uint256,
                uint256,
                address,
                bytes
            )
        );

        owner = tx.origin;

        _setBaseURI(baseURI_, address(this));
        _setDefaultRoyalty(owner, 1000); // set default royalty shares to 10%

        scriptStorageAddress = SSTORE2.write(_script);
    }

    constructor(address factory_) {
        FACTORY = factory_;
    }
    
    
}

Each time a user claims an NFT from our drop, a transaction hash will get generated by the blockchain and can be retrieved and used as input for the script saved at scriptStorageAddress, or more simply by querying our Media API, see section below.

Script Management

The contract allows the owner to set and retrieve a generative script which defines how the NFT's metadata and image are generated.

Setting the Script:

  • _script: The generative script to be stored.

  • The script is written to a specific address using SSTORE2.write, and this address is stored in scriptStorageAddress.

Retrieving the Script:

  • Returns the script as a string by reading from scriptStorageAddress.

NFT Minting with Generative Logic

The minting process involves checking if the caller is eligible based on a Merkle proof, validating payment, and ensuring that minting does not exceed the maximum supply.

Mint Function:

  • _to: Address of the NFT recipient.

  • _merkleProof: Array of bytes32 representing the Merkle tree path to verify.

  • _data: Additional data used during the minting process.

Drop Management

The contract supports timed drops for both allow-listed addresses and the public, with specific pricing for each phase.

Setting Drop Parameters:

  • Drop times, prices, and durations are adjustable only before the start of the drop or before the end of the allow-list (AL) phase.

Administrative Functions

Administrative functionalities allow the owner to configure various aspects of the contract, including royalty information, base URI, and drop mechanics.

Key Administrative Functions:

  • setMerkleRoot: Sets the root of the Merkle tree used for allow-list verification.

  • setBaseURI: Sets the base URI for the NFT metadata.

  • setDropTime, setALPrice, setPublicPrice: Set the specifics of the NFT drop.

Withdrawal of Funds

The contract includes a mechanism for the secure withdrawal of funds accumulated through NFT sales.

Withdraw Function:

  • Transfers the collected fees to the feeRecipient and any remaining balance to the owner.

Initialization and Constructor

Initialization setups up the contract with default parameters passed via the constructor, linking it with a factory contract for potential cloning.

Initialization:

  • Sets initial parameters such as name, symbol, base URI, and other configuration settings.

Conclusion

ERC721Generative is a sophisticated contract designed for projects that require generative art capabilities within the NFT space. It combines the robustness of ERC-721 tokens with advanced features for managing dynamic content creation, making it ideal for artists and developers looking to explore the possibilities of generative NFTs.

Last updated