In this tutorial we will create a non-fungible token (NFT) and deploy to a public testnet.
ERC721 is a standard for representing ownership of non-fungible tokens, that is, where each token is unique such as in real estate or collectibles.
We will use Presets contracts in OpenZeppelin Contracts 3 to create an ERC721 and deploy using Remix.
Setting up the Environment
Open https://remix.ethereum.org/ in your favorite browser.
If you haven't used Remix before, you need to setup plugins so that you can use the Solidity Compiler and Deploy and Run Transactions.
Select the Solidity button under the Environments heading and this will add the required plugins.
The plugins are shown on the left hand column.
Importing the contract
Update (September 2021): Instead of using the Preset contract we can use OpenZeppelin Contracts Wizard to create the Solidity and open in Remix
We are going to use Preset ERC721PresetMinterPauserAutoId
which is an ERC721 that is preset so it can be minted, paused and burned.
We need to import ERC721PresetMinterPauserAutoId
into Remix.
In the File Explorer press the :plus: to Create New File
Call the new file OpenZeppelinPresetContracts.sol
In the new file add the import statement for ERC721PresetMinterPauserAutoId
below.
We specify a minimum version of the Solidity compiler to use and import ERC721PresetMinterPauserAutoId
from GitHub.
Note: When importing via GitHub, you should specify the release tag, otherwise you will get the latest code in the master branch. For OpenZeppelin Contracts you should only use code published in an official release. We will import OpenZeppelin Contracts v3.4.0
. (see Importing from GitHub in the Remix documentation).
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.2;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/presets/ERC721PresetMinterPauserAutoId.sol";
Compile the contract
Select the Solidity Compiler plugin.
Press the Compile button to compile the contract.
The contract and the contracts it inherits from will be loaded into Remix.
The contract will then be compiled.
Deploy the contract
We can deploy our new token to a development blockchain. Providing a name, a symbol and a base URI as parameters to the constructor to create a new ERC721PresetMinterPauserAutoId
.
Select the Deploy & Run Transactions plugin.
Environment should default to JavaScript VM
, our development blockchain.
Change the gas limit to 5000000
Change the Contract to ERC721PresetMinterPauserAutoId
Specify the name, symbol and base URI to use for our new token. I am using "My NFT" and "NFT" and "https://my-json-server.typicode.com/abcoathup/samplenft/tokens/"
Press Deploy.
Remix will deploy our token.
Interact with our Token
We can interact with our deployed token using Remix.
In the Deploy & Run Transactions plugin, under Deployed Contracts expand our deployed token (ERC721PRESETMINTERPAUSERAUTOID
) to show the functions we can interact with. (for help see Deployed Contracts Remix documentation)
Token metadata
We can call the contract functions to read token metadata such as name
, symbol
and baseURI
Press the name
, symbol
and baseURI
function buttons and this will call the functions in our deployed token.
Showing values:
-
baseURI
:0: string: https://my-json-server.typicode.com/abcoathup/samplenft/tokens/
-
name
:0: string: My Token
-
symbol
:0: string: MYT
Mint
We can send a transaction to mint tokens to a given account, from an account with the minter role.
In our case we are minting from the account which deployed the token, which is given the minter role.
We will mint 1 NFT with token ID 0 to our account:
0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2
We can set the parameters as follows
"0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2"
Press mint
The transaction will be shown in the console
We can check the owner of the token and the token URI for the metadata
Showing values:
-
ownerOf
:0: address: 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2
-
tokenURI
:0: string: https://my-json-server.typicode.com/abcoathup/samplenft/tokens/0
MetaData
EIP-721 includes an optional metadata extension with a name
, symbol
and for each tokenID a tokenURI
with can point to a JSON file with name
, description
and image
for the given token ID.
How you create and host this metadata is up to you.
I would suggest using a domain that you control to point to where you host the data so that you can move it as required.
For this tutorial, we will use My JSON Server where we can store a single JSON file in a GitHub repository that we can access via a fake JSON server.
For production we need to store our metadata in a permanent location that can exist for the life of the token.
For images we will use twemoji Graphics from https://github.com/twitter/twemoji which are licensed under CC BY 4.0
A sample JSON for tokenID 0 is:
http://my-json-server.typicode.com/abcoathup/samplenft/tokens/0
Deploy to a public testnet
Next we will deploy to Rinkeby public testnet as OpenSea supports Rinkeby for testing.
You will need the following:
- MetaMask
- A funded testnet account (you can use the Rinkeby social faucet: https://www.rinkeby.io/#faucet)
Deploy to Rinkeby
Set the network in MetaMask to Rinkeby.
Change the environment in Deploy and Run Transactions to Injected Web3
so that Remix uses web3 from MetaMask
Check the gas limit is set to 5000000
Check the Contract is set to ERC721PresetMinterPauserAutoId
Specify the name, symbol and base URI to use for our new token. I am using "My NFT" and "NFT" and "https://my-json-server.typicode.com/abcoathup/samplenft/tokens/"
Press Deploy.
Confirm the transaction in MetaMask
The console will show creation of ERC721PresetMinterPauserAutoId pending...
and we can wait while the transaction is mined.
Mint
We can send a transaction to mint tokens to a given account, from an account with the minter role.
In our case we are minting from the account which deployed the token, which is given the minter role.
We will mint 1 NFT with token ID 0. Specify the address that you want to be the token holder (0x77737a65C296012C67F8c7f656d1Df81827c9541
is one of my test accounts)
Press mint with the recipient address
Confirm the transaction in MetaMask
The console will show transact to ERC721PresetMinterPauserAutoId.mint pending ...
and we can wait while the transaction is mined.
OpenSea
We can validate our metadata
To obtain the address of our contract on Rinkeby we can press the copy button next to our contract
ERC721PRESETMINTERPAUSERAUTOID
My NFT is at: 0x60682c557e061B2f252B39B7763c5A6399a6fc1e
OpenSea metadata validation is at https://rinkeby-api.opensea.io/asset/[nft contract address]/[token id]/validate
My example can be found at:
https://rinkeby-api.opensea.io/asset/0x60682c557e061B2f252B39B7763c5A6399a6fc1e/0/validate/
Assuming that there aren't any issues with our metadata, we can view our NFT on OpenSea at https://rinkeby.opensea.io/assets/[nft contract address]/[token id]
My example can be found at:
Next steps
- Create your artwork and metadata.
- Host your images and metadata in a location that will last the life of the token.
- Define what rights your token holders have.
- Prepare for mainnet.