Movatterモバイル変換


[0]ホーム

URL:


This blog is a work in progress.

writing.

← Check some other posts

Create a fair NFT mint on Ethereum with Solidity and NextJS #2: Smart Contract setup

Anthony Manikhouth
Anthony Manikhouth
Cover Image for Create a fair NFT mint on Ethereum with Solidity and NextJS #2: Smart Contract setup
Anthony Manikhouth
Anthony Manikhouth

Papers, please

In the last post, we've setup a request to our back-end as a requirement of the mint process.

Indeed, we fetched the hash, signature and nonce generated from the back-end and we sent them to the smart contract through thebuy method.

Let's see how we're going to process those informations.

Verify the signer identity

First of all let's add a field that contains the address of the transaction signer to our smart contract. As we saw in the previous post,this address is an account that we own and with which we sign the transaction in our NextJS backend.

addressprivate _signerAddress=0x5260818d61ff27B7d0db3A96310246C041F7191e;// So we can modify the signer address on each drop to enhance securityfunctionsetSignerAddress(address addr)external onlyOwner{ _signerAddress= addr;}

Then we create a function calledmatchAddresSigner to check if the address that signed the hash is the same as the one we set in the contract.

functionmatchAddresSigner(bytes32 hash,bytesmemory signature)privateviewreturns(bool){return _signerAddress== hash.recover(signature);}

Finally, we can use this function as a require in ourbuy method.

require(matchAddresSigner(hash, signature),"DIRECT_MINT_DISALLOWED");

Prevent double minting

Now that we verified the signer identity, we can prevent the same mint from being executed twice. We'll use a simple string-to-boolean map to store the used nonces.

mapping(string=>bool)private _usedNonces;

Then require the nonce to be unique inside ourbuy function.

require(!_usedNonces[nonce],"HASH_USED");

Check hash validity

Now that we've verified the signer identity and the nonce, we can check if the hash is valid. To do so, we'll create a function that recreates the hash from the transaction and compare it to the one we received from the sender.

functionhashTransaction(address sender,uint256 qty,stringmemory nonce)privatepurereturns(bytes32){bytes32 hash=keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32",keccak256(abi.encodePacked(sender, qty, nonce))));return hash;}

Once again, we'll add it to ourbuy function as a require.

require(hashTransaction(msg.sender, tokenQuantity, nonce)== hash,"HASH_FAIL");

The finalbuy method

Now that we've verified the signer identity, the nonce and the hash, thebuy function is pretty much classic, here's the full function:

functionbuy(bytes32 hash,bytesmemory signature,stringmemory nonce,uint256 tokenQuantity)externalpayable{require(saleLive,"SALE_CLOSED");require(!presaleLive,"ONLY_PRESALE");// Check if the address signer is the same as the _signerAddress, preventing direct minting.require(matchAddresSigner(hash, signature),"DIRECT_MINT_DISALLOWED");// This is required to prevent someone from re-using the same signature and hash combination to mint again.require(!_usedNonces[nonce],"HASH_USED");// Verify if the keccak256 hash matches the hash generated by the hashTransaction functionrequire(hashTransaction(msg.sender, tokenQuantity, nonce)== hash,"HASH_FAIL");// Out of stock checkrequire(totalSupply()< TOTAL_SUPPLY,"OUT_OF_STOCK");require(publicAmountMinted+ tokenQuantity<= DISTRIBUTED_TO_PUBLIC,"EXCEED_PUBLIC");require(tokenQuantity<= MAX_PER_MINT,"EXCEED_MAX");require(PRICE* tokenQuantity<= msg.value,"INSUFFICIENT_ETH");for(uint256 i=0; i< tokenQuantity; i++){ publicAmountMinted++;_safeMint(msg.sender,totalSupply()+1);}// Add the nonce to the list of already used nonce _usedNonces[nonce]=true;}

In the final post, we'll see how to add some fair minting logic to our smart contract with the whitelisting method.

Check out theGitHub repository for the full source.


[8]ページ先頭

©2009-2025 Movatter.jp