Prerequisites
Installing Foundry
If you're on a Mac or are using Linux run this command in your terminal
curl -L https://foundry.paradigm.xyz | bash
If you're on Windows, it is recommended that you install wsl and then use the same command. However, if you don't want to install wsl, you'll have to build it from source. Make sure you have the Rust compiler and cargo on your machine. Check if you do by using this command:
rustc --version
cargo --version
Once confirmed, use this command
cargo install --git https://github.com/foundry-rs/foundry --profile local --locked forge cast chisel anvil
Setting up Foundry
To build the smart contract, we will use Foundry this time. It is an Ethereum development environment and framework that allows full-stack Ethereum development on your local computer without relying on browser IDEs such as Remix. It also allows for easier debugging, faster iterations, and writing scripts and tests to go along with your contract code.
To set up a Foundry project, first create a new folder on your computer - we will name ours NFT-Tutorial - and go to it through your Terminal.
Once your Terminal is inside NFT-Tutorial, setup a Foundry project using the following:
forge init foundry-app
Installing OpenZeppelin Contracts
cd into foundry-app and then run the following command:
forge install OpenZeppelin/openzeppelin-contracts
This will fetch Openzeppelin's contracts repository from GitHub and clone it, enabling us to use it in our code.
When you do this, Hardhat would have looked at the import statement and understood you're trying to import a Solidity file that is not one part of your own project . It would then fetch it from the node_modules/ folder because it expects you to have installed the npm dependency for it.
In Foundry, this works a bit differently. Since this is not a Node project and doesn't ship with npm - and instead just git clones the repository you need into the lib folder, imports would normally work something like this:
import {ERC20} from "../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
But this code doesn't look that clean - so we have remappings.
Remappings are essentially a way to provide an alias to imports - a shorter-way of writing import statements which are aliasing some short-form path to the real path of that dependency.
To configure them in your project and make sure they're picked up when compiling your code, run the following command:
forge remappings > remappings.txt
This will take the remappings it has understood, and write them to a remappings.txt file in foundry-app which acts as a configuration file for all your remappings. You can also customize this and add new ones if you need to.
Writing the NFT Contract
With OpenZeppelin Contracts now installed, we can move on to writing our Solidity code.
Create a new Solidity file - we'll name ours NFTee.sol - inside the src folder of your Foundry project. Write the following code in that file:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
// Import the openzepplin contracts
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
// NFTee is ERC721 signifies that the contract we are creating imports ERC721 and follows ERC721 contract from openzeppelin
contract NFTee is ERC721 {
constructor() ERC721("NFTee", "ITM") {
// mint an NFT to yourself
_mint(msg.sender, 1);
}
}
The code is fairly straightforward. We import the ERC-721 contract from OpenZeppelin, and then initialize it during the constructor. We also use the internal _mint function to mint an NFT to ourself.
To make sure you got the code right check if all the files are compiling. First delete the test folder and then, in your terminal, run
forge build
If there are no errors and your contract compiled just fine, you are good to go!
Deploying the Contract
Let's deploy this contract to the Sepolia Test Network. First, create a .env file inside your foundry-dapp folder and add the
following lines to it:
QUICKNODE_RPC_URL="..."
PRIVATE_KEY="..."
Head over to Quicknode and sign up for an account if you haven't already. Quicknode is a node provider that runs blockchain nodes for various networks and gives you access to them so you don't have to run your own. We will use them to deploy our contract through Foundry by connecting Foundry to their node.
After creating an account at Quicknode, click on Create an Endpoint, select Ethereum and then select the Sepolia network. Finish this process, and then copy the HTTP Provider link you receive. Update your .env file to have that URL as the value for QUICKNODE_RPC_URL.
Now, for the private key. When you deploy using Remix, Remix just prompts you to deploy the contract through MetaMask since it operates in the browser. However, since we are running Foundry directly on your computer, we need to give it the private key directly.
To get your private key, you can export it from MetaMask. To do so, open up MetaMask, click on Account Details for the account you want to export, and click on Export Private Key. Copy-paste the value and put it in your .env file as the value for PRIVATE_KEY.
Now we'll have to load our environment variables into the terminal's environment. For doing this, run the following command in your terminal
source .env
This command just specifies that the source of the variables we're about to enter is the .env file.
Finally, to deploy your contract, run the following command:
forge create --rpc-url $QUICKNODE_RPC_URL --private-key $PRIVATE_KEY src/NFTee.sol:NFTee
Notice how variable names are prefixed with $
This command will output some logs to your console where it will compile your contract and then deploy to the Sepolia Test Network. It will also give you the contract address of the deployed contract.
Copy the contract address it gives you, and look it up on Sepolia Etherscan - open up the first transaction there and it will show you that a NFT was minted and transfered to your address!
Congratulations!
Awesome! If you got this far, you have probably deployed your first NFT contract to an Ethereum testnet! You also learnt about Foundry and setting it up.
If you had any trouble, or just want to share your success, message me for help!
Thanks for reading my post.
Happy coding!