- Intro
- Fungible vs Not
- Ethereum Token Standards
- Prerequisited - Set up the environment
- Deploy an NFT Contract
- Up Next
- Further Reading - the very short list
- Exercises
- Sample Code
Consider an app that tracks student progression. Teachers have the authority to confer qualifications upon a student after completing a course (or at checkpoints along the way). Somthing like a qualification certificate is a perfect use case for a non-fungible token. Most paper documents of this sort contain some basic info: title, name, date, authority, potential expiry, logo or signature, etcetera. Lets say you wanted to present your diploma to an institution to prove that you had already completed some Programming classes, it is likely the diploma would not be enough. The registrar at the potential school would have to contact your previous school to validate the claim. If only there was a trustless decentralised system that allowed for easy verification? Hmm....
Q: Are Coins Tokens?
If you have some bitcoin or ether, yes, these are digital tokens because they are fungible, secure, scarce, transferrable, and have monetary value and utility. (Bitcoin's utility is widely considered to be a store-of-value.) Its confusing at first but there is a difference between value and utility. In Bitcoin's case the utility is value. For Ethereum there is broader application, e.g., using ether to purchase an NFT or invest in a new project or pay gas fees. Many tokens claim some form of utility and let value be determined by a market. It is a regulatory grey area when it comes to classifying tokens as securities or otherwise, and has implications for taxation and reporting.
Currency tokens (and cash) are interchangeable, or fungible, because it doesn't matter what specific token you have, everyone agrees on the same value. If people were willing to pay a premium for specific tokens or characteristics, then the overall utility of the medium as money begins to fall apart. This is the problem with barter; there is far too much subjective difference in value between objects for people to easily exchange goods directly.
Think of paintings in a gallery. All the paintings are similar in many respects─composed of paint, multicolour, framed canvas, 2-dimensional, etc.─however, each painting is obviously unique with value determined by many external factors. Non-fungible tokens, where each unit is unique, are designed for this purpose. In a digital manner they implement security and scarcity. Value and use are subjective like gallery paintings, but these now inherit the open, permissionless, censorship-resistant properties of the blockchain.
NFTs aren't just for collectibles, art, and profile pictures. Any document or data structure that can be digitised can be represented as an NFT: music, certificates, degrees, licenses, passes, patents, title deeds, concert tickets, contracts, voting rights, et-cetera.
Over time standards have emerged that assist developers with creating new projects, building functionality, and interacting with other tokens, contracts, and chains. Some of the main standards that have been developed for Ethereum are:
The first use case of Ethereum was generating new coins. These projects often launched with fundraising efforts called ICOs (initial coin offerings) that promised buyers a certain allocation of new tokens. All these tokens live inside (or on) the Ethereum blockchain but are separate from ether. Think of tokens as carriages that run on the rails of Ethereum and the whole train is powered by ether. The Ethereum Request for Comments #20 is the standard that defines how to make a fungible token that is compatible with Ethereum itself. Because its an open network anyone is free to make their own token and launch it on Ethereum1. The contract will live forever on the blockchain and handle functions like transfers, account balances, token creation and destruction. These tokens can be divided into as small as eighteen decimal places (0.000 000 000 000 000 001
) to allow for very small and fractional payments.
Examples of the ERC-20 standard include the following tokens (among many):
DAI
the decentralized algorithmic stablecoin,LINK
the decentralized oracle network, andwBTC
wrapped bitcoin.
ERC-721 is a standard that includes an integer variable called tokenID
that must be unique. From the EIP: "In general, all houses are distinct and no two kittens are alike. NFTs are distinguishable and you must track the ownership of each one separately." Any tokens deployed with this standard cannot be subdivided, and ownership is wholly transferred.
Examples of the ERC-721 standard include:
- CryptoKitties collectibles and game,
- Ethereum Name Service domain registrar, and
- the Bored Ape Yacht Club collectibles and club membership.
Further to the previous two standards, the 1155 standard merges both fungible and non-fungible into a new standard that extends functionality. Called a Multi-token standard it can batch transfer groups of items, for example, if your game character kills another it can transfer the plundered items to the winner in a single transaction. It also improves efficiency with a focus on game design where a large number of transfers could be required and it would be cumbersome for the user to stop gameplay to interact with a smart contract and pay associated gas fees.
Examples of the ERC-1155 standard include:
- OpenSea the NFT marketplace,
- Skyweaver the game, and
- The Sandbox metaverse platform.
We'll need the following tools in our environment before we can get going.
- MetaMask account with some testnet ether. See our previous steps for this here.
- Alchemy account to communicate with Ethereum. Head to https://www.alchemy.com/ and sign up for free. We listed this as an option to get Goerli testnet ETH. The Alchemy accounts allows you to communicate with an Ethereum full node via an API. Other ways to do this are through your own hosted full node, or through Infura, for example.
- Node.js for running javascript applications (download link), and NPM the node package manager to download and install packages. Windows and Mac install instructions here.
The Composer
tool will create a query to post to the blockchain. In this case its using a JSON RPC. I'll use the account address that (should) already have testnet ETH
And the response:
This value "result":"0x16d2798836302a2"
is in hexadecimal and can be converted to decimal as 102781902492205730
. Recall that ether has 18 decimal places, and this value is in wei
. Dividing by 0.10278
ETH.
- (i) Create a new working directory for your project:
mkdir my-nft-app
- (ii) Navigate there:
cd mkdir my-nft-app
- (iii) Initialize package:
npm init
. I answered as follows with blanks fortest command
,git repository
, andkeywords
:
{
"name": "my-nft-app",
"version": "1.0.0",
"description": "NFTs for course credits",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jeff",
"license": "ISC"
}
4. Install Hardhat
Within your app directory type: npm install --save-dev hardhat
. Hardhat is a dev environment for Ethereum that helps with deploying & debugging smart contracts & apps and all that jazz.
Within your app directory type: npx hardhat
and select Create an empty hardhat.config.js
to see a welcome message
- (i) Create a folder for organization: Type
mkdir contracts
- (ii) Create a new file in the
\contracts
folder; mine is calledcourseNFT.sol
This code is based on the OpenZeppelin standard. Copy and paste the code (file is here). You can modify the name and tokenID in the constructor:constructor() ERC721("courseNFT", "ccNFT") {}
. The namecourseNFT
must match the contract name. Save the file. - (iii) Install the OpenZeppelin Library via:
npm install @openzeppelin/contracts
- (i) Get your Alchemy API URL by clicking
VIEW KEY
in your dashboard. It should look like:https://eth-goerli.g.alchemy.com/v2/FU3d...dctz
- (ii) Export your private key from MetaMask by clicking the hamburger menu,
Account Details
, andExport Private Key
- (iii) Create an environment file to store our keys. From the command line:
npm install dotenv --save
. Now create a.env
file that contains:
API_URL="https://eth-goerli.g.alchemy.com/v2/FU3d3...cdctz"
PRIVATE_KEY="97a08...be6b3d"
Warning
Never commit these with version control like git or GitHub! If you do so accidentally they must be regenerated immediately.
Back at the command line: npm install --save-dev @nomiclabs/hardhat-ethers ethers@^5.0.0
In the project root directory edit the hardhat.config.js
file with all of our information:
/**
* @type import('hardhat/config').HardhatUserConfig
*/
require('dotenv').config();
require("@nomiclabs/hardhat-ethers");
const { API_URL, PRIVATE_KEY } = process.env;
module.exports = {
solidity: "0.8.1",
defaultNetwork: "goerli",
networks: {
hardhat: {},
goerli: {
url: API_URL,
accounts: [`0x${PRIVATE_KEY}`]
}
},
}
In the command line compile the contract with Hardhat: npx hardhat compile
. You should get a success message:
If you have already compiled the contract and nothing has changed, then the message will say: Nothing to compile
In your project root create a folder for organization. Type mkdir scripts
. Create a new file called deploy.js
in the \scripts
folder. It will contain:
async function main() {
const CourseNFT = await ethers.getContractFactory("courseNFT")
// Start deployment, returning a promise that resolves to a contract object
const courseNFT = await CourseNFT.deploy()
await courseNFT.deployed()
console.log("Contract deployed to address:", courseNFT.address)
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error)
process.exit(1)
})
In the command line: npx hardhat --network goerli run scripts/deploy.js
and you should get a response address where the contract now lives (permanently) on the (testnet) blockchain!
Copy the address and go to https://goerli.etherscan.io/ and search for it.
Remember your Alchemy dashboard? It now will register the details. Check that the from
address matches your MetaMask.
- What can we do with our contract? We'll call it ofcourse. In the next tutorial we'll look into calling the mint function.
- This has been based on this Tutorial from Ethereum.org
- https://nftschool.dev/ looks like a promising resource
- What are some examples of fungible tokens compared to non-fungible tokens that you use that are not blockchain related?
- How much gas did you pay to deploy your contract? What are some implications of the gas auction fees model?
- Include a link to your contract deployment transaction on https://goerli.etherscan.io/ or similar testnet.
Files be found here
Footnotes
-
This is often a tutorial exercise when learning about blockchains. Launching a self-token contract on the mainnet is expensive due to gas fees, but you can easily launch one on a testnet. ↩