Lazy minting of ERC721 NFTs using EIP712 standard for typed, structured data. ✨
Lazy minting of ERC721 NFTs using EIP712 standard for typed, structured data. ✨
Lazy minting or Signature minting is a mechanism to mint NFTs (or any kind of Token) just in time, without paying the gas fees upfront, and let the user pay for it along with the price of the NFT, if any.
In traditional minting, the token is minted to a specific address, or transferred to it after minting. While for lazy minting, an authorized contract admin approves an external request/voucher and enables them to mint the token in the admin's contract.
A mint voucher or request is a struct that needs to be signed by the authorized contract admin. It has all the parameters for the NFT to be minted, aswell as additional metadata such as the price, the currency to be used.
The voucher is then hashed using the EIP712 standard and signed by the authorized contract admin. Once signed, the signer can be retrieved any time by recovering it using ECDSA algorithm from the signature. This can be used to ensure that the voucher is not tampered with, and is signed by someone who is authorized to mint tokens.
Here, we use 2 parameters to check if a specific voucher is valid.
uuid
specified in the voucher has been minted. We use a mapping for UUID with their mintedmapping(bytes32 => bool) private minted;
)MINTER_ROLE
role in the contract, as we use AccessControlEnumerable
from OpenZeppelin library. This canThe whole process is divided into 3 main steps.
The mint voucher payload generation. The contract admin creates a payload containing the details based on the
parameters of the voucher. The parameters are validated, and the price is converted from the native token or
the ERC20 token (if specified in the currency
) into gwei
(1e9 wei). And then it's ready to be signed.
The voucher signing by the authorized contract admin. The payload generated is then signed using the ECDSA
algorithm(ECDSA.toTypedDataHash
), and the signature is returned.
Minting tokens using the signed voucher. Once the signature is generated, it's forwarded to the external
account trying to mint the token. Using the signatureMint
function (or whatever you name it), the signature
is validated first, then the NFT is minted to the specified address. The price is deducted if specified from
the native tokens/ERC20, whichever is specified.
This is the struct that holds the parameters for the voucher.
struct MintVoucher {
bytes32 uuid;
address to;
string uri;
uint256 price;
address currency;
address paymentReceiver;
}
The parameters can be described as so:
Parameter | Type | Usage |
---|---|---|
uuid | bytes | The UUID generated for having unique signatures. This is autogenerated. |
to | address | The address where the NFT will be sent to. Defaults to address(0)
|
uri | string | The URI containing all the metadata for the NFT to be minted. |
price | integer | The price for the NFT to be minted. Defaults to 0 . |
currency | address | The address of the currency to be paid in. Defaults to the native currency address. |
paymentReceiver | address | The creator of the NFT or the address, who receives the payment of the price for the NFT. |
The voucher can be verified with the function provided in the SignatureMint
contract.
function verify(MintVoucher calldata voucher, bytes calldata signature)
public
view;
This function uses the 2 validation steps mentioned above to ensure that the voucher is valid.
And, the signed voucher can be redeemed using the following function in the NFT
contract.
function signatureMint(MintVoucher calldata voucher, bytes calldata signature)
external
payable
nonReentrant;
This uses the verify
function internally to ensure it's valid. If it is, it processes the payment and mints the
NFT as specified.
Hardhat tasks are provided with the contracts in order to test the signature mint process and make it easy for anyone to use it.
Firstly, install the dependencies to get started.
npm install -D
# OR
yarn
Next, build the contracts.
yarn run build
Every task is run on the local network. If you want to use a different network, use the --network
option as
--network mumbai
. You can check the networks supported in the hardhat config file.
You can deploy the contract using the following task:
npx hardhat deploy:NFT --name "My NFT contract" --symbol MNFT
The flags for this task are:
Flag | Optional | Usage |
---|---|---|
name |
NO | The name of the NFT contract |
symbol |
NO | The symbol to be used for the tokens by the contract |
This task allows you to generate a signed voucher.
npx hardhat nft:generate-signature
The flags for this task are:
Flag | Optional | Usage |
---|---|---|
contract |
NO | The address of the deployed NFT contract |
metadata |
NO | The URI containing metadata for the NFT to be minted |
paymentreceiver |
NO | The address which receives the payment for the NFT |
to |
Yes. Defaults to Zero address. | The address which receives the NFT. |
price |
Yes. Defaults to zero. | The price for the NFT. |
This task allows you to verify the signed voucher for validity.
npx hardhat nft:verify-signature
The flags for this task are:
Flag | Optional | Usage |
---|---|---|
contract |
NO | The address of the deployed NFT contract |
signedpayload |
NO | The signed payload to be verified for validity generated from generate-signature task |
This task allows you to verify the signed voucher for validity.
npx hardhat nft:signature-mint
The flags for this task are:
Flag | Optional | Usage |
---|---|---|
contract |
NO | The address of the deployed NFT contract |
signedpayload |
NO | The signed payload to be verified for validity generated from generate-signature task |
Contributions, issues and feature requests are welcome. After cloning & setting up project locally, you can just submit a PR to this repo and it will be deployed once it's accepted.
⚠️ It’s good to have descriptive commit messages, or PR titles so that other contributors can understand about your commit or the PR Created. Read conventional commits before making the commit message.
We love people's support in growing and improving. Be sure to leave a ⭐️ if you like the project and also be sure to contribute, if you're interested!