> For the complete documentation index, see [llms.txt](https://super-piccell.gitbook.io/embryo/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://super-piccell.gitbook.io/embryo/crypto/smart-contract/embryo-nft.md).

# Embryo NFT

## SPEN Contract (SuperPiccellEmbryoNFT)

{% hint style="danger" %}
This documentation is for a prototype contract and the specifications may be updated.
{% endhint %}

### Overview <a href="#overview" id="overview"></a>

The `SPEN` contract is designed to mint full on-chain NFTs using content data retrieved from the **SuperPiccellCore** contract. The content stored in the core contract is minted as a unique NFT, ensuring that each piece of content can only be minted once. This contract supports both free and paid minting, and can accept either **Ether (ETH)** or **ERC20 tokens** as payment. The contract also includes features for managing minting configurations, checking content protection, and burning tokens.

This contract is highly flexible, allowing it to be customized and adapted for other NFT minting processes. It can be easily integrated into a wide range of projects, making it an ideal solution for decentralized content management and NFT minting.

You can view the contract on the Sepolia testnet at the following links:

* [SPEN Contract GitHub repository](https://github.com/dev-muhus/superpiccell-embryo-nft)
* [SPEN Contract on Sepolia Etherscan](https://sepolia.etherscan.io/address/0x05952136c42C0cDFd6FC7A274Eb145Ea65C1Aa87#code)

### **Frontend Application (DApp)**

<figure><img src="https://1004805861-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fx3rbWes8hihfSSMCr6JL%2Fuploads%2FIjuZtIt1STzxc2LjM5BF%2F%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202024-09-13%2014.12.25.png?alt=media&amp;token=b2f8210f-aebd-41ff-9727-5b17b1087dc4" alt=""><figcaption></figcaption></figure>

The frontend application (DApp) provides an intuitive interface for minting NFTs directly from content stored in the `SuperPiccellCore` contract. Users can browse and select content from the core contract, and mint it as a full on-chain NFT. Additionally, the DApp performs necessary checks to ensure that the selected content:

* Is not already minted.
* Is not locked or protected.
* Complies with the minting configuration set in the contract.

If all conditions are met, users can proceed with minting the NFT, either for free or by paying with Ether or ERC20 tokens.

You can also interact with the contract using our Frontend Application (DApp) which is available at [SuperPiccell Embryo NFT DApp](https://superpiccell-embryo-nft.vercel.app/).

#### Features of the DApp

* **Content Retrieval**: The DApp retrieves content from the `SuperPiccellCore` contract and displays it to users for minting.
* **Minting Checks**: The application ensures that the content has not already been minted and that it is not protected by the core contract’s content protection mechanism.
* **Customization**: The DApp can be customized to modify the user interface, design, and minting logic. This flexibility makes it easy to adapt the application to other NFT minting use cases or projects.
* **Reusable Architecture**: The DApp can be reused for different content or NFT minting projects by simply swapping out the core contract or modifying the minting logic.

#### Interaction with the DApp

To interact with the DApp, users will need a browser extension such as MetaMask that allows their browser to connect to the Ethereum blockchain. Users must switch their MetaMask network to the Sepolia testnet and ensure that they have enough Ether or the configured ERC20 tokens in their wallet to pay for minting if applicable.

You can add the Sepolia network to MetaMask by using [chainlist](https://chainlist.org/) or manually adding it from the settings menu in MetaMask.

The DApp is built using the **React** JavaScript library and communicates with the Ethereum blockchain using **ethers.js**, providing a seamless and efficient user experience.

<div align="left"><figure><img src="https://1004805861-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fx3rbWes8hihfSSMCr6JL%2Fuploads%2FcWzU2hE0yL9RNoug6Liw%2Fimage.png?alt=media&amp;token=ce6f392b-17b2-460b-968f-f1219c5ddadc" alt=""><figcaption></figcaption></figure></div>

#### Environment Requirements for the DApp

* PC: MetaMask, Trust Wallet, Coinbase Wallet
* Smartphone: MetaMask

### Features

| Function Name        | Description                                                                                                                                                                |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setMintingEnabled`  | Enables or disables minting. This function can only be called by the owner of the contract.                                                                                |
| `setMintPrice`       | Sets the price for minting an NFT. This function can only be called by the owner of the contract.                                                                          |
| `setPaymentToken`    | Sets the ERC20 token to be used for minting payments. If not set, ETH will be used as the payment currency. This function can only be called by the owner of the contract. |
| `mintNFT`            | Mints a new NFT with the specified content. Can be done for free or with payment based on the configuration. Each content ID can only be minted once.                      |
| `getMintConfig`      | Retrieves the current minting configuration, including minting status, price, payment token, and whether free minting is allowed.                                          |
| `paymentTokenSymbol` | Returns the symbol of the payment token (ERC20). If no payment token is set, returns "ETH" for Ether.                                                                      |
| `totalSupply`        | Returns the total number of minted NFTs.                                                                                                                                   |
| `tokenURI`           | Returns the URI of a specific token ID, as long as it has not been burned.                                                                                                 |
| `withdraw`           | Allows the owner to withdraw Ether that was sent to the contract.                                                                                                          |
| `withdrawToken`      | Allows the owner to withdraw ERC20 tokens from the contract.                                                                                                               |
| `receiveToken`       | Allows the owner to receive ERC20 tokens sent to the contract.                                                                                                             |

### Security Features

| Function Name   | Description                                                                                                          |
| --------------- | -------------------------------------------------------------------------------------------------------------------- |
| `burn`          | Burns an NFT and invalidates its associated content. It also unlocks the content ID, allowing it to be minted again. |
| `withdraw`      | Allows the contract owner to withdraw Ether from the contract.                                                       |
| `withdrawToken` | Allows the contract owner to withdraw ERC20 tokens from the contract.                                                |
| `receiveToken`  | Allows the owner to receive ERC20 tokens from the contract.                                                          |

### Minting Process

#### Minting Conditions

The minting process is subject to the following conditions:

1. Minting must be enabled (`mintingEnabled == true`).
2. The content ID must not have been minted before (`_mintedContentIds[contentId] == false`).
3. If minting is not free (`isFreeMint() == false`):
   * **Ether Payments**: If no payment token is set (`paymentToken == address(0)`), the caller must send the required Ether (`msg.value >= mintPrice`).
   * **ERC20 Payments**: If a payment token is set (`paymentToken != address(0)`), the caller must transfer the required ERC20 tokens to the contract (`paymentToken.transferFrom()`).

#### Free Mint

The `isFreeMint()` function checks whether minting is free. If the mint price is set to `0`, minting is considered free.

#### Mint Configuration

The minting configuration is accessible via the `getMintConfig()` function, which returns:

* **mintingEnabled**: Whether minting is currently enabled.
* **mintPrice**: The price of minting in either Ether or ERC20 tokens.
* **paymentTokenAddress**: The address of the ERC20 token used for minting, or `0x0` for Ether.
* **isFreeMint**: Whether minting is free.
* **paymentTokenSymbol**: The symbol of the payment token used for minting (e.g., "ETH", "DAI").

### Token Transfers

The contract supports withdrawing Ether and ERC20 tokens. The owner can:

1. **Withdraw Ether**: Using the `withdraw()` function, the contract owner can transfer any Ether held in the contract to their own address.
2. **Withdraw ERC20 Tokens**: Using the `withdrawToken(IERC20 _token)` function, the contract owner can transfer ERC20 tokens held in the contract to their own address.
3. **Receive ERC20 Tokens**: The owner can receive ERC20 tokens by calling the `receiveToken(IERC20 _token, uint256 _amount)` function.

### Burn Mechanism

When an NFT is burned using the `burn(uint256 tokenId)` function:

* The NFT is permanently removed.
* The content ID associated with the burned NFT is reset, allowing it to be minted again in the future.
* The token is marked as burned in the `_burnedTokens` mapping to ensure that its URI can no longer be accessed.

### Data Structure

* **Token IDs**: The token IDs are auto-incremented starting from `0` and are unique to each NFT minted.
* **Content IDs**: Each token is associated with a content ID, which must be unique across minted tokens.
* **Minted Content IDs**: A mapping `_mintedContentIds` is used to track whether a content ID has been minted or not.

***

#### Important Notes:

* This contract uses `ERC721URIStorage`, which allows storing token metadata on-chain.
* The contract is equipped with `ERC721Burnable` to allow burning of tokens, and `Ownable` to manage ownership and security.
* Minting can be configured to either use Ether or an ERC20 token for payments.
* The contract supports fallback and receive functions to handle incoming Ether and tokens, but Ether cannot be used for minting when an ERC20 payment token is set.
