Giter Site home page Giter Site logo

lazy-minting's Introduction

Lazy Minting outline

Motivation

Minting an NFT on a blockchain "mainnet" generally costs some amount of money, since writing data into the blockchain requires a fee, or gas, to pay for the computation and storage. This can be a barrier for artists and other NFT creators, especially those new to NFTs who may not want to invest a lot of money up front before knowing whether their work will sell.

Using a few advanced techniques, it's possible to defer the cost of minting an NFT until the moment it's sold to its first buyer. The gas fees for minting are rolled into the same transaction that assigns the NFT to the buyer, so the NFT creator never has to pay to mint. Instead, a portion of the purchase price simply goes to cover the additional gas needed to create the initial NFT record.

Minting "just in time" at the moment of purchase is often called lazy minting, and it has been adopted by marketplaces like OpenSea to lower the barrier to entry for NFT creators by making it possible to create NFTs without any up-front costs.

This guide will show how lazy minting works on Ethereum, using some helper libraries from OpenZeppelin.

Overview

For lazy minting to work, we need a smart contract function that the NFT buyer can call that will both mint the NFT they want and assign it to their account, all in one transaction.

Before we get started, let's look at a non-lazy minting function:

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract EagerNFT is ERC721URIStorage, AccessControl {
  using Counters for Counters.Counter;
  Counters.Counter _tokenIds;

  bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

  constructor(address minter)
    ERC721("EagerNFT", "EGR") {
      _setupRole(MINTER_ROLE, minter);
    }

  function mint(address buyer, string tokenURI) {
    require(hasRole(MINTER_ROLE, msg.sender), "Unauthorized");
    
    // minting logic
    _tokenIds.increment();
    uint256 tokenId = _tokenIds.current();
    _mint(buyer, tokenId);
    _setTokenURI(tokenId, tokenURI);
  }
}

This contract builds on the OpenZeppelin ERC721 base contract, adding role-based Access Control.

In the mint function, we require that the caller has the MINTER_ROLE, ensuring that only authorized minters can create new NFTs.

In the lazy minting pattern, we need to change things a bit:

pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;

contract LazyNFT {
  bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

  constructor(address minter)
    ERC721("LazyNFT", "LAZ") {
      _setupRole(MINTER_ROLE, minter);
    }

  struct NFTVoucher {
    uint256 tokenId;
    uint256 minPrice;
    string uri;
  }

  function redeem(address redeemer, NFTVoucher calldata voucher, bytes memory signature) public payable {
    address signer = _verify(voucher, signature);
    require(hasRole(MINTER_ROLE, signer), "Invalid signature - unknown signer");

    // minting logic...
  }

  function _verify(NFTVoucher voucher, bytes memory signature) private returns (address signer) {
    // verify signature against input and recover address, or revert transaction if signature is invalid
  }
}

We'll get to the signatures and minting logic in a second. First, notice that we have a new struct named NFTVoucher. An NFTVoucher represents an un-minted NFT which hasn't yet been recorded. To turn it into a real NFT, a buyer can call the redeem function and pass in a voucher, plus a signature of the voucher that's been prepared by the NFT creator.

This contract still has role-based access controls, but we've changed things up a bit. Instead of checking that msg.sender is an authorized minter, we allow anyone to call the redeem function. The access controls are used to make sure that the signature was produced by someone authorized to mint NFTs. This works because verifying an Ethereum signature returns the address of the signer, so we can validate the voucher and learn who created it in one operation.

lazy-minting's People

Contributors

yusefnapora avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.