Creating NFTs with Remix: Complete ERC721 Smart Contract Development Tutorial
Author of this section: @LiKang
this presentation will briefly introduce how to develop and test a smart contract.
In this tutorial, we will use Remix run Solidity contract.
Remix ethereum's official recommend Smart Contracts Integrated Development Environment (IDE), suitable for novices, provides an easy-to-use interface to quickly write, compile and deploy smart contracts in the browser without the need to install any programs locally. In the following advanced courses, we will also introduce contract Local Development and Test Environment .
Solidity is a door for the realization smart Contracts while creating a high-level programming language. This language has been C++ , Python and Javascript the influence of language, the design purpose is to be able to in the Ethernet virtual machine ( EVM ) run on. Solidity is a statically typed language that supports inheritance, libraries, and complex user-defined types.
Initializing the contract
panel
enter Remix , We can see the interface as shown in the figure below:
as you can see, Remix it consists of three panels and a terminal.
- Icon panel-Tap to change the plug-ins displayed in the side panel.
- Side panel-The interface for most plugins (not all plugins) is here.
- Main panel-Great page display that takes on editing files, tabs, and some tools.
- Terminal-for viewing transaction receipts and various logs.
Icon Panel
A brief introduction to the function of the icon in the lower bar, which we will use in more detail later. Home always open the main page, even if it is closed. File explorer use to manage workspaces and files. Search is a global search function. Solidity Compiler is the contract compiler interface, which displays the basic configuration items of the compiler and Advanced Configurations button to open the Advanced Configuration panel.Deploy&Run is to send the transaction to the current environment in. Debugger is a debugger that displays the state of the contract when debugging a transaction. Plugin mananer it is a plug-in manager, which has a lot of plug-ins to choose to install. Setting there will be some basic settings, such language , theme , Github access token , regular Settings wait.
Workspaces and Files
Remix in WORKSPACES is a special folder that separates items. Files from one workspace cannot be imported or accessed from a different workspace.
As shown in the figure below, click icon 1 to switch different workspaces, and Icon 2 Create , Clone , Rename, Download , Delete and so on a series of operations for the workspace.
Create
our tutorial this time is through Create button to demonstrate.
When we click Create will pop up Create Workspace the pop-up window, Remix the following templates are available:
- Basic
- Blank
- OpenZeppelin ERC20
- OpenZeppelin ERC721
- OpenZeppelin ERC1155
- 0xproject ERC20
- Gnosis MultiSig
when choosing a OpenZeppelin library's ERC721 template, you can add additional functionality.
ERC721(Ethereum Request for Comments 721), proposed by William Entriken, Dieter Shirley, Jacob Evans and Nastassia Sachs in January 2018, is a non-homogeneous token standard for implementing modern coin APIs in smart contracts. OpenZeppelin is a library for secure smart contract development, built-in standard implementations of many commonly used contracts.
Tick on Mintable , indicating that we have added to the template contract. Mint method, and then click OK .
To here, our Workspace new is built. The following figure:
.deps directory is what we installed @openzeppelin the npm package, which is installed here, is quoted in our contract. Contract Template and referenced in the contract template toolkit . contracts the following is the contract document written by myself. scripts Under the folder is an automatically generated script file for the deployment contract. Executing the js file below can also implement the deployment contract. tests some test files for automatic verification are automatically written inside.
@openzeppelin provided to us. ERC721 contract templates are in contracts/MyToken.sol let's briefly understand the content of this contract.
- Line 1 is a comment that will write down the software license used for this code (
license), used here isMIT license. If you do not write permission, you will be warned at compile time (warning), but the program can run.soliditythe annotation//at the beginning, followed by the content of the comment (will not be run by the program). - Line 2 declares
solidityversion, because different versions have different syntax. This line of code means that the source file will not allow less0.8.20version or greater than or equal0.9.0the compiler compiles (the second condition is compiled.^provided).Soliditystatement with a semicolon (;) at the end. - Lines 4-5 are importing external
Solidityfile, directedSoliditydocuments and their ownSoliditythe file is equivalent to becoming the sameSoliditycontract. - Line 7 is to create a contract (
contract), and state the name of the contractMyToken,isindicates that the introducedERC721andOwnablecontract. - Lines 8-10 are in
constructorwe pass in the parameters defined by the inherited contract,.ERC721incomingtokenofnameandsymbol,Ownablethe address of the contract owner. - Lines 13-15 define
publicopen to the outside worldsafeMintmethod, you need to pass in a typeaddressoftoparameter and type isuint256oftokenId, executed in the methodERC721.solthe contract private method referenced in_Safemint ()and brought in the parameterstoandtokenId.
Next, we will try to write some of our custom functions into the contract template.
Development Contract
we continue to understand the function of the contract to write and compile tests.
In the following code we simply implement a new mint method to replace the default generated safeMint , New mint the method is consistent with the method interface we used in the previous chapter, so that when we deploy the contract, we can replace the course contract with the new contract.
Specific modifications are:
- put
initialOwnerset as the contract issuer, which makes it easier to deploy the contract without specifying it.initialOwner. - Defines a file named
_Nexttokenidtype isuint256contract Private Variablesprivate, used to mark the current progress, each new NFT value needs to be increased by one; - in
mintmethod requires that the type passed in beuint256ofquantity, representing how many NFT to cast this time. Here, let's simplify the logic and limit the casting to one at a time. - Remove
onlyOwnermodifier, so that anyone can callmintmethod. - Add
payablemodifier, so that you can callmintmethod of people can transfer money to the contract at the same time. _Safemintalso read_Mintthis is mainly to avoid reporting an error when calling the contract through the Remix contract later,toalso correspondingly readmsg.sender, represents NFT casting to the address initiating the transaction.
The code is as follows:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyToken is ERC721, Ownable {
+ uint256 private _nextTokenId = 0;
- constructor(address initialOwner)
+ constructor()
ERC721("MyToken", "MTK")
- Ownable(initialOwner)
+ Ownable(msg.sender)
{}
- function safeMint(address to, uint256 tokenId) public onlyOwner {
+ function mint(uint256 quantity) public payable {
+ require(quantity == 1, "quantity must be 1");
+ require(msg.value == 0.01 ether, "must pay 0.01 ether");
+ uint256 tokenId = _nextTokenId++;
- _safeMint(to, tokenId);
+ _mint(msg.sender, tokenId);
}
}private refers to methods and variables that can only be called in the pre-deployment contract, while public methods and variables are accessible to everyone.
Test Contract
- unit Test Plugin
we need to click on the bottom left corner Plugin mananerIcon Search in Plug-in Manager unit keyword, and then the search results appear SOLIDITY UNIT TESTING , click Activate , Install the activation plug-in, as shown in the figure below:
and then, Solidity unit testing the icon of will appear in the left icon bar, clicking on which will load the plugin in the side panel.
After successful loading, the plugin should look like this:
- unit Test File
Remix injects a built-in assert library that can be used for testing. You can view the documentation for the library here here. .
In addition, Remix allows some special functions to be used in the test file to make the test more structural. They are:
beforeEach()-Run before each testbeforeAll()-Run before all testsafterEach()-Run after each testafterAll()-Run after all tests
our unit test files, in the directory tests/MyToken_test.sol this is because the template contract we chose automatically helped us create the test contract. If we are a new blank folder, then we need to click through Generate button to generate the test file, as shown in the following figure:
and then we're in File explorer click on our test file tests/MyToken_test.sol and write the following test content:
remix_tests.solbyRemixautomatic injection;remix_accounts.solgenerated a list of addresses for our test accounts;../contracts/MyToken.solintroduced the contract documents we have written;- in
beforeAll()instantiate our contract.MyTokendefinedsand take a test address and save itTestsAccounts.getAccount(0)definedacc0; testTokenNameAndSymbol()the instantiated contract is verified inname()the value to get isMyToken,symbol()the valueMTK;- writing Functions
testMint(), call ourmint(1)method, cast oncebalanceOf()value should be1;
tests/MyToken_test.sol the file code is as follows:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0 <0.9.0;
import "remix_tests.sol";
import "remix_accounts.sol";
import "../contracts/MyToken.sol";
contract MyTokenTest {
MyToken s;
function beforeAll () public {
s = new MyToken();
}
function testTokenNameAndSymbol () public {
Assert.equal(s.name(), "MyToken", "token name did not match");
Assert.equal(s.symbol(), "MTK", "token symbol did not match");
}
/// #value: 10000000000000000
function testMint() public payable {
s.mint{value: msg.value}(1);
Assert.equal(s.balanceOf(address(this)), 1, "balance did not match");
}
}the single test of Remix is to call the contract we want to test in a contract to test, the specific will not be launched first, you can refer documentation for the Remix unit test plug-in .
- Run unit tests
when we have finished writing the test, select the file and click Run to perform the test. The execution will run in a separate environment. After the execution of a file is complete, the following test summary is displayed:
here, the unit test of our contract is completed.
Of course, if you're better at using the Chai and Mocha tests, Remix also supported.
Chai is a BDD / TDD assertion library for Node.js and browsers that can be happily paired with any JavaScript testing framework. Mocha is a feature-rich JavaScript testing framework that runs on Node.js and browsers, making asynchronous testing easy and fun.
Just create a js file, it is best to create it in scripts folder. Then right-click the new and write the test code. js file, click Run .
Probably like this:
click Run , the results will be displayed on the terminal after the test is executed.
This is just an example, providing ways and means to operate, if you are good at this way, it is fully supported.
Next, we'll try to document the contract that we 've written. Compile and deployment Chain .











