Home

Use Foundry with Dijets Utility Chain

Introduction#

This guide shows how to deploy and interact with smart contracts using foundry on a local Dijets Utility Chain running on a local test network.

Foundry toolchain is a smart contract development toolchain written in Rust. It manages your dependencies, compiles your project, runs tests, deploys, and lets you interact with the chain from the command-line.

Requirements#

  • You have installed Foundry. This installation includes the forge and cast binaries used in this walk-through.

DijetsNodeGo and Dijets Network Runner#

DijetsNodeGo is a Dijets node implementation written in Go.

Dijets Network Runner is a tool to quickly deploy local test networks. Together, you can deploy local test networks and run tests on them.

Start a local five node Dijets network:


_10
cd /path/to/dijets-up
_10
# start a five node staking network
_10
./go run examples/local/fivenodenetwork/main.go

Getting Started#

This section will walk you through creating an ERC721 Token.

Clone Dijets Smart Contracts Guide Repo#

Clone the quickstart repository and install the necessary packages via yarn.


_10
git clone https://github.com/Dijets-Inc/dijets-smart-contracts-guide.git
_10
cd dijets-smart-contracts-guide
_10
yarn

In order to deploy contracts, you need to have some test DJT in your wallet. You can get testnet DJT from Dijets Faucet, that transfers a small amount of test DJT tokens for you to play around with.

Write Contracts#

We’ll use a sample ERC721 contract to track items in our game, which will each have their own unique attributes. Whenever one is to be awarded to a player, it will be minted and sent to them. Players are free to keep their token or trade it with other people as they see fit, as they would any other asset on the blockchain The smart contract is in the repo we cloned earlier for this example GameNFT.sol found in ./contracts folder.


_30
//SPDX-License-Identifier: MIT
_30
// contracts/ERC721.sol
_30
_30
pragma solidity >=0.6.2;
_30
_30
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
_30
import "@openzeppelin/contracts/utils/Counters.sol";
_30
_30
contract GameNFT is ERC721 {
_30
using Counters for Counters.Counter;
_30
Counters.Counter private _tokenIds;
_30
_30
constructor() ERC721("GameItem", "GMT") {}
_30
//
_30
_30
// commented out unused variable
_30
// function awardItem(address player, string memory tokenURI)
_30
function awardItem(address player)
_30
public
_30
returns (uint256)
_30
{
_30
_tokenIds.increment();
_30
_30
uint256 newItemId = _tokenIds.current();
_30
_mint(player, newItemId);
_30
// _setTokenURI(newItemId, tokenURI);
_30
_30
return newItemId;
_30
}
_30
}

Let's examine this implementation of an NFT as a Game Item. We start by importing to contracts from our node modules. We import OpenZeppelin's open source implementation of the ERC721 standard which our NFT contract will inherit from. Our constructor takes the _name and _symbol arguments for our NFT and passes them on to the constructor of the parent ERC721 implementation. Lastly we implement the awardItem function which allows anyone to mint an NFT to a player's wallet address. This function increments the currentTokenId and makes use of the _mint function of our parent contract.

Compile & Deploy with Forge#

Forge is a command-line tool that ships with Foundry. Forge tests, builds, and deploys your smart contracts.

To compile the NFT contract run:


_10
forge build

By default the compiler output will be in the out directory. To deploy our compiled contract with Forge we need to:

  1. Set environment variables for the RPC endpoint.
  2. Specify the private key with test DJT to deploy the contract.

Set your environment variables by running:


_10
export RPC_URL=<YOUR-RPC-ENDPOINT>
_10
export PRIVATE_KEY=<YOUR-PRIVATE-KEY>

Since we are deploying to a local testnet, our RPC_URL export should be:


_10
export RPC_URL=http://127.0.0.1:9650/ext/bc/C/rpc

Once set, you can deploy your NFT with Forge by running the command below while adding the values for _name and _symbol, the relevant constructor arguments of the NFT contract:


_10
forge create NFT --rpc-url=$RPC_URL --private-key=$PRIVATE_KEY --constructor-args GameItem GMT

Upon successful deployment, you will see the deploying wallet's address, the contract's address as well as the transaction hash printed in our terminal.

Here's an example output from an NFT deployment.


_10
[⠔] Compiling...
_10
No files changed, compilation skipped
_10
Deployer: 0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC
_10
Deployed to: 0x52c84043cd9c865236f11d9fc9f56aa003c1f922
_10
Transaction hash: 0xf35c40dbbdc9e4298698ad1cb9937195e5a5e74e557bab1970a5dfd42a32f533

Note: Please store your Deployed to address for use in the next section.

Using Cast to Interact with the Smart Contract#

We can call functions on our NFT contract with Cast, Foundry's command-line tool for interacting with smart contracts, sending transactions, and getting chain data. In this scenario, we will mint a Game Item to a player's wallet using the awardItem function in our smart contract.

Mint an NFT from your contract by replacing <NFT-CONTRACT-ADDRESS> with your Deployed to address and <NFT-RECIPIENT-ADDRESS> with an address of your choice.


_10
cast send --rpc-url=$RPC_URL <NFT-CONTRACT-ADDRESS> "awardItem(address)" <NFT-RECIPIENT-ADDRESS> --private-key=$PRIVATE_KEY

Upon successful completion, the command line will display the transaction data.


_13
blockHash 0x1d9b0364fe002eeddd0e32be0c27d6797c63dffb51fe555ea446357759e6a6f8
_13
blockNumber 3312
_13
contractAddress
_13
cumulativeGasUsed 90837
_13
effectiveGasPrice 28000000000
_13
gasUsed 90837
_13
logs [{"address":"0x45857b942723fff8ee7acd2b1d6515d9965c16e5","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000845095a03a6686e24b90fed55e11f4ec808b1ab3","0x0000000000000000000000000000000000000000000000000000000000000001"],"data":"0x","blockHash":"0x1d9b0364fe002eeddd0e32be0c27d6797c63dffb51fe555ea446357759e6a6f8","blockNumber":"0xa37d50","transactionHash":"0x4651ae041a481a6eeb852e5300e9be48e66a1d2332733df22d8e75cf460b0c2c","transactionIndex":"0x0","logIndex":"0x0","removed":false}]
_13
logsBloom 0x00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000040000000000000000000000000008010000000000000000040000000000000000000000000000020000040000000000000800000000002000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000060080000000000000000000000000000000000000000000000000000000000000000
_13
root
_13
status 1
_13
transactionHash 0x4651ae041a481a6eeb852e5300e9be48e66a1d2332733df22d8e75cf460b0c2c
_13
transactionIndex 0
_13
type 2

Thats it! You just minted your first NFT from your contract using Cast from Foundry. You can check the owner of tokenId 1 by running the cast call command below:


_10
cast call --rpc-url=$RPC_URL --private-key=$PRIVATE_KEY <NFT-CONTRACT-ADDRESS> "ownerOf(uint256)" 1

The address you provided above should be returned as the owner.


_10
0x000000000000000000000000845095a03a6686e24b90fed55e11f4ec808b1ab3

Join us on Qowalts to learn more or for any questions you may have.