0

I want users to mint NFTs on my ERC1155 contract but I don't want to pay the gas fees but I only want them to mint if I allow them so I was thinking maybe I would sign a transactinon on the backend, and let the frontend user execute this transaction? I'd probably need a nonce to stop replay? idk if this makes sense?

1 Answer 1

0

If you are OK with a pre-defined set of whitelisted addresses and how many times each should be able to mint, you can do this in constant amount of additional gas.

There's a ton of ways you can achieve an off-chain whitelist.

The typical way I've seen involves generating a Merkle tree of all whitelisted addresses off-chain and committing its root to the chain (usually embedded directly in the contract's code). Then you could publish the Merkle tree and have the users supply a Merkle proof (that their address is included in the Merkle tree described by the Merkle root committed to the chain) when they try to mint. Your contract would validate that the Merkle proof is valid, OpenZeppelin has an implementation of Merkle proof validation you could use.

This way, you only need to commit a small amount of data to the chain (the Merkle root) but you can whitelist as many addresses as your heart desires in your Merkle tree!

Generating the Merkle proof probably isn't a simple task for the layman, so projects would typically integrate the proof generation into the minting interface.

End-to-end your process might look something like this:

  1. Generate a Merkle tree merkle_tree from a set of whitelisted addresses whitelisted_addresses = {address_1, address_2, ...}.
  2. Compute the Merkle root of merkle_tree, call it merkle_root.
  3. Commit merkle_root to Ethereum, probably by hard-coding it in your contract so you can reference it easily.
  4. Introduce a new (or modify your existing) mint function to also take in a merkle_proof.
  5. In your mint function verify that merkle_proof is a valid proof of inclusion of the message sender's address in merkle_tree, hence verifying that this address is a whitelisted address. merkle_root is already in your contract, so you can do this verification. Reject if it isn't valid.
  6. In your minting front-end, pull the user's address and check if it is a whitelisted address (this can be done in whatever way you want). If it is, then compute a Merkle proof of inclusion of this user's address in merkle_tree, say merkle_proof. When a user mints, send merkle_proof to your contract with the mint.

Edit: if you don't have a pre-defined set of whitelisted addresses or you don't know how many times each should be able to mint.

This would cost additional gas per mint, but you don't need to pay that cost up-front.

One idea would be to have your contract expect a signed message containing a nonce (and whatever information you want) with the mint. Your contract would verify the signature and check that the nonce has not been used before. If everything checks out, then you mark the nonce as used (and modify whatever other state you need to modify) and mint the token.

You can optimize the gas usage for the caller in a number of ways here, depending on your usage. In some cases (e.g. if you don't care about the signatures being independent of the message caller) you can drop the nonce and instead just track that addresses aren't minting more than some set number that you signed (i.e. sign (address, maxToMint) instead of (nonce, )).

An implementation of the nonce-based approach would look something like the following:

  1. Store the public key (or address) of the signer on the contract, call it signer_address.
  2. Modify your mint function to take in a nonce and a signature.
  3. Have your mint function verify that signature is a valid signature of nonce by signer_address (OpenZeppelin has implementations that help you do this).
  4. If it is valid, check that nonce has not been used before (i.e. by querying a mapping or otherwise).
  5. If the nonce has not been used before, you know that this is a nonce that has been generated by you and it hasn't been used so you can mint.
  6. To allow a user to mint, you'd give them the nonce and the signed message. They would forward that to the contract (you can embed this into the UI).

Here's a blog post that talks about this a bit more: https://medium.com/@PhABC/off-chain-whitelist-with-on-chain-verification-for-ethereum-smart-contracts-1563ca4b8f11

5
  • Hi Ziyad, thanks for the answer. I'm not sure this is quite what I was looking to do; it seems this involves whitelisting a set of addresses in advanced, to mint in the futuer. I'm wanting to whitelist individual (one-off) mints, for a particular address - they then won't be able to do any more, unless they get another signature from me.
    – Tobi
    Mar 6, 2022 at 16:34
  • In essence, I'd like to hand over a signed transaction from my backend to the public allowing them to be played by the frontend - but not replayed. The goal being to delegate the gas fees to the frontend - rather than paying them myself, for everyone, on the backend
    – Tobi
    Mar 6, 2022 at 16:36
  • Ah I see! I edited my answer. I thought you were trying to not incur this gas fee totally, not just to offload it. Mar 6, 2022 at 23:38
  • One idea would be to have your contract expect a signed message containing a nonce (and whatever information you want) with the mint. Your contract would verify the signature and check that the nonce has not been used before. If everything checks out, then you mark the nonce as used (and modify whatever other state you need to modify) and mint the token. this is just what I was thinking - I just wanted to check whether the idea was dumb / whether there were better ways to do it - for example I realised that I'd have to store the nonce within the contract, to verify its not been used later
    – Tobi
    Mar 7, 2022 at 11:57
  • I was thinking I could make the signature independent of the caller (address) as I don't really care who actually makes the request, just that the request is made by someone else who is willing to pay the gas fee - I.e. someone who wants to mint their work, and is willing to pay a gas fee to do so
    – Tobi
    Mar 7, 2022 at 11:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.