Gm gm! 👋🏼
Thanks to everyone's responses to our NFT series. In the previous tutorials, we've covered creating, minting, and viewing an NFT on Mantle Network, and, also adding price to that NFT via making modifications to the smart contract.
In this tutorial, you will write and deploy an ERC-1155 smart contract on Mantle Network using the following tools:
- MetaMask
- Solidity
- Hardhat
- OpenZeppelin Contracts
You may already be acquainted with the two primary standards for symbolizing tokens on Ethereum:
- ERC-20: Regularizes fungible tokens (or currencies).
- ERC-721: Regularizes non-fungible tokens (or NFTs).
If you're managing a blockchain project of any complexity (like a game, NFT PFF collection, etc.), you'll likely need both tokens and contracts to manage them. Also, ERC-721 NFTs have become notorious for their excessively high minting and batch transfer expenses.
Addressing these limitations, the Ethereum community formulated a new standard called ERC-1155. This standard facilitates the creation of both fungible and non-fungible tokens under the same contract, considerably reducing minting and transfer charges. Before we begin, a quick shoutout to the amazing Alchemy team for their dev education resources, which have been a great reference for various tutorials throughout! Of course, you can always ask questions on Mantle Network's Discord at any point! Let's get started 💪🏼
Step 1: Install Node and npm
If you haven't already, install node and npm on your local machine.
Make sure that node is at least v14 or higher by typing the following in your terminal:
node -v
Step 2: Create a MetaMask Wallet
We need an Ethereum wallet to send and receive transactions. For this tutorial, we’ll use MetaMask, a browser extension wallet.
You can download and create a MetaMask account for free here. Once you have an account, make sure to switch to the “Mantle Network” in the upper right. If you haven't added Mantle Network on MetaMask, follow this guide to easily get onboard onto Mantle Network via Metmask.
Step 3: Get $MNT from Mantle Testnet Faucet
To implement our smart contract on the Mantle Network, we'll need some $MNT for testing. You can get this easily through Mantle Network's official faucet.
Step 4: Create a Hardhat project
We're going to set up our project using Hardhat, the industry-standard development environment for Ethereum smart contracts. Additionally, we'll also install OpenZeppelin contracts.
To set up Hardhat, run the following commands in your terminal:
mkdir mantle_erc1155-contract && cd mantle_erc1155-contract
npm init -y
npm install --save-dev hardhat
npx hardhat
Note: Choose the Create a Javascript project option from the menu and accept all defaults. To verify everything is installed properly, run this command in your terminal:
npx hardhat test
To install OpenZeppelin, run the following commands in your terminal:
npm install @openzeppelin/contracts
Step 5: Write the smart contract
Shoutout to the Alchemy team for coming up with this smart contract to explain the ERC-1155 use case with ease. Let's write a smart contract that implements the assets in a game using tokens. Our game will consist of two fungible currencies (gold and silver), two fungible weapons (sword and shield), and one non-fungible crown.
Open the project in your favorite code editor (e.g., VS Code), and create a new file called AwesomeGame.sol in the contracts folder. Add the following code to this file:
// SPDX-License-Identifier: MITpragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
contract AwesomeGame is ERC1155 {
uint256 public constant GOLD = 0;
uint256 public constant SILVER = 1;
uint256 public constant SWORD = 2;
uint256 public constant SHIELD = 3;
uint256 public constant CROWN = 4;
constructor() ERC1155("https://awesomegame.com/assets/{id}.json") {
_mint(msg.sender, GOLD, 1018, "");
_mint(msg.sender, SILVER, 1018, "");
_mint(msg.sender, SWORD, 1000, "");
_mint(msg.sender, SHIELD, 1000, "");
_mint(msg.sender, CROWN, 1, "");
}
}
Do note that we have minted both fungible and non-fungible tokens from the same contract, a feat not possible with ERC-20 and ERC-721.
Additionally, remember that we have passed a metadata URI to the ERC-1155 constructor. Passing this metadata permits us to link each token ID with NFT-like metadata, regardless of whether it is fungible or non-fungible.
For instance, using an ERC-1155, we can associate an image of a gold coin with tokens linked to GOLD. This would not have been possible had we established GOLD as a separate ERC-1155 contract. ⚠️ Still don't understand the gibberish above!? Don't worry, we've included a detailed line-by-line explanation of the contract at the end of the tutorial! ⬇️ Compile the contract and make sure everything is working by running the following command in your terminal:
npx hardhat compile
Step 6: Connect Mantle Network to your project
Having created a MetaMask wallet and a smart contract, we can now interlink them. To accomplish this, we'll employ the dotenv package.
Install the dotenv pack in your project directory by running the following command from your terminal:
npm install dotenv --save
Create a .env file in the root directory of our project. Note: Your .env file must only be named .env. Do not change the name to any form xx.env.
Add your MetaMask private key and HTTP Alchemy API Key (from Step 2: Create an Alchemy app) to your .env file.
PRIVATE_KEY = 0x___your__private___key
Step 7: Update hardhat.config.js
Replace the contents of hardhat.config.js with the following code:
require("dotenv").config();
require("@nomicfoundation/hardhat-toolbox");
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.4",
networks: {
"mantle-testnet": {
url: "https://rpc.testnet.mantle.xyz/",
accounts: [process.env.PRIVATE_KEY], // Uses the private key from the .env file
}
}
};
Step 8: Write the Deployment Script
With our contract ready and our configuration file set, it’s time to write the contract deployment script.
Navigate to the scripts folder and create a new file called deploy.js , and add the following code:
const hre = require("hardhat");
async function main() {
const factory = await hre.ethers.getContractFactory("AwesomeGame");
const [owner] = await hre.ethers.getSigners();
const contract = await factory.deploy();
await contract.deployed();
console.log("Contract deployed to: ", contract.address);
console.log("Contract deployed by: ", owner.address, "\n");
console.log("Tokens have been minted successfully!");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Run the script using the following command:
npx hardhat run scripts/deploy.js
You should see output that looks something like this:
Notice that every wallet we marked as eligible to receive an airdrop now has an NFT balance of 1. The owner/creator of the project was responsible for minting all the NFTs as well as paying the gas fees associated with it.
Step 9: Deploy the Contract on Mantle Network
Now, let’s deploy our contract to Mantle Network. In the terminal, run the following command:
npx hardhat run scripts/deploy.js --network mantle-testnet
If all goes well, you should see the following output:
We can check the deployed contract on Mantle Explorer as well.
Add: A detailed explanation of ERC-1155 contract used above
*Please skip this part if you've already understood the contract used in the tutorial! *🦄
The contract used in Step-6 demonstrates how the ERC-1155 standard can be used for minting both fungible tokens (like gold and silver, which are indistinguishable units) and non-fungible tokens (like the crown, a unique item), all in a single smart contract. This characteristic of ERC-1155 makes it more gas efficient and flexible compared to using separate ERC-20 and ERC-721 contracts.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
This portion of the code establishes that the contract is licensed under the MIT license, and specifies that it uses the Solidity programming language, version 0.8.4. It also imports the ERC-1155 token standard implementation from the OpenZeppelin smart contracts library.
contract AwesomeGame is ERC1155 {
This line defines a new contract named "AwesomeGame". The "is" keyword indicates that the new contract inherits from the ERC-1155 contract imported earlier from OpenZeppelin.
> uint256 public constant GOLD = 0;
> uint256 public constant SILVER = 1;
> uint256 public constant SWORD = 2;
> uint256 public constant SHIELD = 3;
> uint256 public constant CROWN = 4;
These lines declare constant unsigned integer values for each token ID that the contract will support. Each ID is linked with a specific game asset: gold, silver, sword, shield, and crown. The "public" keyword means that these values are publicly accessible on the blockchain.
constructor() ERC1155("https://awesomegame.com/assets/{id}.json") {
This is the constructor function, which is called only once when the contract is first deployed. It's inheriting from the ERC-1155 constructor and takes a URI as a parameter. The URI is a link to the metadata for the ERC-1155 tokens. It contains a placeholder {id}
, which will be replaced by the token ID when queried, allowing each token to have distinct metadata while using a shared schema.
_mint(msg.sender, GOLD, 1018, "");
_mint(msg.sender, SILVER, 1018, "");
_mint(msg.sender, SWORD, 1000, "");
_mint(msg.sender, SHIELD, 1000, "");
_mint(msg.sender, CROWN, 1, "");
These lines mint (create) a certain amount of each token and assign it to the account deploying the contract (represented by msg.sender). For example, the account deploying the contract gets 1018 of GOLD, 1018 of SILVER, 1000 each of SWORD and SHIELD, and 1 CROWN. The final parameter in each _mint function call is the data parameter, left as an empty string in this contract.
Wrap
Amazing! You're now equipped to craft and implement ERC-1155 contracts.
🛑 Have doubts and need support? Join our Discord Server and ping the DevRel team for support or interact with other blockchain developers and fellow builders!
💪🏼 Not tired and want to keep building? Head over to https://www.mantle.xyz/blog/developers and check out an amazing list of tutorials to keep building cool stuff on Mantle Network!
Ciao! 👋🏼