# Lazy Mint Extension ERC1155

### Intro

Another common ask is how to do lazy-minting with Manifold. If you're unfamiliar, lazy-minting is a technique by which minting costs are passed on to the buyer. This makes sense in many situations (especially collectible-style projects), but does not make sense in others. We'll take a look at the contract and how to deploy it here, but I would not suggest doing this for collections of less than, say, 20 tokens. The reason for this is that deploying an extension costs gas! And on a smaller scale, the savings from lazy-minting are less than the cost to deploy the contract.

Anyway, let's take a look. We'll do this with an ERC1155 contract, but something similar can be done with ERC721s.

### Contract

```
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@manifoldxyz/libraries-solidity/contracts/access/AdminControl.sol";
import "@manifoldxyz/creator-core-solidity/contracts/core/IERC1155CreatorCore.sol";
import "@manifoldxyz/creator-core-solidity/contracts/extensions/ICreatorExtensionTokenURI.sol";

import "@openzeppelin/contracts/utils/introspection/ERC165.sol";

contract Tutorial2 is AdminControl, ICreatorExtensionTokenURI{

    address private _core;
    string private _baseURI;

    function initialize(address core) public adminRequired {
      _core = core;

      address[] memory to = new address[](1);
      to[0] = msg.sender;
      uint[] memory amounts = new uint[](1);
      amounts[0] = 1;
      string[] memory uris = new string[](1);
      uris[0] = "";

      IERC1155CreatorCore(_core).mintExtensionNew(to, amounts, uris);
    }

    function mint() public {
      address[] memory to = new address[](1);
      to[0] = msg.sender;
      uint[] memory tokenIds = new uint[](1);
      tokenIds[0] = 1;
      uint[] memory amounts = new uint[](1);
      amounts[0] = 1;

      IERC1155CreatorCore(_core).mintExtensionExisting(to, tokenIds, amounts);
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(AdminControl, IERC165) returns (bool) {
        return interfaceId == type(ICreatorExtensionTokenURI).interfaceId || AdminControl.supportsInterface(interfaceId) || super.supportsInterface(interfaceId);
    }

    function setBaseURI(string memory baseURI) public adminRequired {
      _baseURI = baseURI;
    }

    function tokenURI(address core, uint256 tokenId) external view override returns (string memory) {
        require(core == _core, "Invalid token");
        return _baseURI;
    }
}

```

Let's walk through the contract here before we think about deploying it.

The first function we have there is called `initialize` and this is where we set ourselves up by minting the first copy of the token. In this case, we've hard-coded it to token #1. It is important to note that we're taking the assumption here that the extension will only be used for this token. When we call this function, we're saving the address of our *core* contract, and calling the `mintExtensionNew` function on it to mint the token.

The `mint` function is where we allow other people to mint more copies of this token. You can see that it is pretty simple, it prepares the input, and then calls `mintExtensionExisting` to mint another copy of an existing token (token #1 that we made in `initialize`).

The `supportsInterface` function simply tells other contracts that are calling this one what functions it supports.

The `setBaseURI` function lets us set the tokenURI we want to return. It also lets us update this information at any time in the future.

The `tokenURI` function returns this URI. It is important to note that this *does not* follow the EIP-1155 spec (as the extension does not keep track of tokens itself, it only helps mint them). The base contract, of course, has the `uri` function specified by the spec.

### How to Deploy

1. Deploy your creator contract using Manifold Studio (in this example, you will want a 1155 contract)
2. Deploy the *extension* contract above using [remix](https://remix.ethereum.org/).
3. Register the extension with write as proxy function `#9: registerExtension` on your creator contract from step 1. You can access this function by visiting the etherscan page for your contract, then clicking `contract` -> `write as proxy`. You will want to enter the address from the extension contract from *step 2* in the `extension` parameter, and a blank space for the `baseURI` parameter.\
   ![](https://268636785-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8n4plerMUJrsrAiaKpc2%2Fuploads%2FW2aC0rij59u5wRhx2f5Q%2FScreen%20Shot%202023-03-19%20at%206.28.01%20AM.png?alt=media\&token=d4dae8df-ce9e-4c76-bd3a-3feeda3d92eb)
4. Set the baseURI for your extension with write function `#4. setBaseURI`. You can do this in via remix, or via the etherscan page for the extension contract.
5. Initialize the extension with write function `#2: initialize`. You can do this in via remix, or via the etherscan page for the extension contract.
6. Mint with write function `#3. mint`. You can do this in via remix, or via the etherscan page for the extension contract.

You should be able to see your token on OpenSea TestNet via:\
<https://testnets.opensea.io/assets/\\>\<CREATOR\_CONTRACT\_ADDRESS>/1

There are just a couple things to note here. The first is that this is token #1 on the *creator* contract. Notice the OpenSea URL which has the address of the *creator* contract. There are 2 tokens, and 2 owners. 1 of the tokens is owned by the wallet I called `initialize` with, and the other is owned by a wallet I called `mint` with.

### FAQ

**Is this contract an ERC1155 contract?**

No - but it helps you mint tokens on an ERC1155 contract (your *core* contract)

**Can this deployed contract be re-used?**

Not in its current form. However, an extension can be written in such a way that it manages tokens for many different *core* contracts.

**What is the gas cost for deploying an extension like this?**

This particular extension cost me 1,833,652 gas to deploy. At gas prices of 40 gwei, that would be about 0.07 ETH.
