This is lesson 4 of the Smart Contracts 101 free course by Rohas Nagpal.
There are 2 ways to build a Smart Contract:
Option 1: Start from scratch and code it yourself.
Option 2: Use the OpenZeppelin collection of secure & tested smart contracts as building blocks.
I strongly recommend option 2 - it minimizes risk by using "battle-tested libraries" of smart contracts for Ethereum and other blockchains.
This post will walk you through the process of creating an ERC721 token (commonly called a non-fungible token) with the OpenZeppelin Contracts Wizard.
1. Let’s get started
Go to the OpenZeppelin Contracts Wizard and click on ERC721.
Here’s what your screen will look like:
Enter the name & symbol e.g. Rohas Nagpal & ROHAS.
Let’s add https://www.rohasnagpal.com as the base URI. This will be concatenated with token IDs to generate the token URIs.
Here’s what your code will look like:
Here’s what it means:
// SPDX-License-Identifier: MIT
This is a comment indicating that the smart contract is licensed under the MIT License, a permissive open-source license.
pragma solidity ^0.8.9;
This line specifies the version of the Solidity compiler required to compile the smart contract. In this case, it requires a version compatible with 0.8.9.
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
This line imports the ERC721 contract from the OpenZeppelin library.
contract RohasNagpal is ERC721
This line defines a new smart contract called "RohasNagpal" that inherits from the ERC721 contract imported from OpenZeppelin. By inheriting the ERC721 contract, RohasNagpal will have all the standard functionality of an ERC721 token.
constructor() ERC721("Rohas Nagpal", "ROHAS")
This is the constructor of the RohasNagpal contract. It will be called only once when the contract is deployed. The constructor calls the constructor of the ERC721 contract with two parameters: the name of the token ("Rohas Nagpal") and the symbol of the token ("ROHAS").
When deployed, this smart contract will create a new ERC721 token named "Rohas Nagpal" with the symbol "ROHAS", utilizing the well-tested and secure OpenZeppelin ERC721 contract as its foundation.
function _baseURI() internal pure override returns (string memory) {return "https://www.rohasnagpal.com";
This is a function that overrides the _baseURI() function of the ERC721 contract. It returns the base URI for the tokens, which is the URL "https://www.rohasnagpal.com".
2. Let’s add some features
Now you can tick/check the various options under the FEATURES section. As you check an option, you will notice that some code gets added.
Here’s what each option means:
Mintable
Mintable: Privileged accounts will be able to create more supply.
function _baseURI() internal pure override returns (string memory) {return "https://www.rohasnagpal.com";
This function allows the contract owner to mint new tokens. It calls the _safeMint() function of the ERC721 contract, which mints a new token and assigns it to the specified address.
Burnable
Burnable: Token holders will be able to destroy their tokens.
contract RohasNagpal is ERC721, ERC721Burnable, Ownable {
ERC721Burnable is another OpenZeppelin contract that extends ERC721 and adds the functionality to burn (or destroy) tokens. This can be useful if a token needs to be removed from circulation or if a mistake was made when creating a token.
Pausable
Pausable: Privileged accounts will be able to pause the functionality marked as whenNotPaused. Useful for emergency response.
This defines two public functions:
pause
unpause
These can only be called by the contract owner to pause & unpause the token contract, respectively.
Additionally, it overrides the internal _beforeTokenTransfer function to ensure transfers are only allowed when the contract is not paused.
Votes
Votes: Keeps track of historical balances for voting in on-chain governance, with a way to delegate one's voting power to a trusted account.
Enumerable
Allows on-chain enumeration of all tokens or those owned by an account. Increases gas cost of transfers.
URI Storage
Allows updating token URIs for individual token IDs.
3. Let’s set the access control
Now you can tick/check the various options under the ACCESS CONTROL section. These options restrict who can access the functions of a contract or when they can do it.
Here’s what each option means:
Ownable: Simple mechanism with a single account authorized for all privileged actions.
Roles: Flexible mechanism with a separate role for each privileged action. A role can have many authorized accounts.
4. Let’s add upgradeability
Now you can tick/check the various options under the UPGRADEABILITY section. Smart contracts are immutable by default unless deployed behind an upgradeable proxy.
Here’s what each option means:
Transparent: Uses a more complex proxy with higher overhead, and requires fewer changes in your contract. Can also be used with beacons.
UUPS: Uses simpler proxy with less overhead, and requires including extra code in your contract. Allows flexibility for authorizing upgrades.
5. Let’s add a security contact
Enter the email address where people can contact you to report security issues.
6. Download your smart contract code
You can download the code by clicking on the Download button in the top right corner of the wizard.
7. Compile the smart contract
Now that the code for the smart contract has been written, it needs to be compiled into bytecode that can be executed by the Ethereum Virtual Machine (EVM).
This is typically done using an Integrated Development Environment (IDE) like Remix. An IDE is a software application that provides tools for writing, testing, and debugging code.
Now click on the Open in Remix button on the top right corner of the wizard.
Note: Make sure to use the same version of a compiler that is mentioned in your code.
Click on Compile contract.
After a few seconds, you will see a green tick in the right column:
8. Deploy the smart contract
Once the smart contract has been written & compiled, it can be deployed to the blockchain (e.g. Ethereum). This involves sending a transaction to the blockchain network that contains the bytecode for the smart contract.
Click on the Ethereum logo below the green tick.
A screen like this will show up.
Select the environment / test network.
Your Metamask wallet will open up. Select your account address, and then click on Deploy.