When it comes to writing smart contracts, developers only need to know one language, such as Solidity, Vyper, or Rust. However, choosing a framework and learning all the languages around that framework can be tricky.
Learning a minimalistic command line framework like DappTools removes these issues, and makes life as a Web3 developer much easier.
In this DappTools tutorial, you’ll learn how to create, test, and deploy your smart contracts through the DappTools framework.
Check out the video to accompany this tutorial:
What Is DappTools?
DappTools is a framework like Hardhat and Brownie that helps smart contact developers test, deploy, and maintain their code. If you deploy a contract, where do you store the compiled bytecode? How are you keeping track of where it went? How easy is it to redeploy new code? All these are issues solved by using a smart contract development framework.
DappTools was originally written in Haskell. Recently however, the Paradigm team adopted DappTools and rewrote it in Rust, calling their new creation Foundry. Both work similarly in that they are command line-focused, fast, and often involve writing Solidity tests with a lot of fuzzing.
DappTools is a popular choice for a number of leading protocols.
Why Use DappTools?
What Are We Learning?
In this tutorial, we are going to learn how to:
- Work with DappTools
- Deploy Chainlink-powered hybrid smart contracts using the dapptools-starter-kit
Here are a few examples of using Chainlink services with this starter kit:
First, we need to install a few things.
You probably already have it installed, but if not you’ll need
make. Follow these steps to check whether you have it installed.
Once we have installed these tools, we can clone the starter kit repo and begin working on it.
sh git clone https://github.com/smartcontractkit/dapptools-starter-kit cd dapptools-starter-kit make # This installs the project's dependencies. make test
Now you have the files, let’s go through what everything does:
Makefile: Where you put your scripts. DappTools is command line based, and our makefile helps us run large commands with a few characters.
lib: This folder is for external dependencies, like OpenZeppelin or ds-test.
out: Where your compiled code goes. Similar to the build folder in Brownie or the artifacts folder in Hardhat.
src: This is where your smart contracts are. Similar to the contracts folder in Brownie and Hardhat.
Let’s do some testing! To test we can run either
make test or
All the commands from DappTools work with this repo, including
Importing External Dependencies
Let’s say we want to create an NFT using the OpenZeppelin standard. To install external contracts or packages, we can use the
dapp install command. We need to name the GitHub repo organization and the repo name to install.
First, we need to commit our changes so far. DappTools brings external packages in as git submodules, so we need to commit first.
git add . git commit -m ‘initial commit’
Then, we can install our external packages. For example, for OpenZeppelin, we’d use:
dapp install OpenZeppelin/openzeppelin-contracts
You should now see a new folder in your lib folder labeled openzeppelin-contracts, since it’ll have downloaded from GitHub. This repo already starts with OpenZeppelin contracts, so there’s been some duplication, but we still got to see how it works.
To deploy, you first need to setup your
ethsign and your
Set Up Your Account/ethsign
To get your private keys into DappTools, you can either use a keystore or
ethsign comes with the install of
ethsign, run the following:
bash ethsign import
You’ll now be prompted for your private key and a password. You can get a private key from a wallet like MetaMask. Once successful, add the address of the private key to your
.env file under an
ETH_FROM variable. See the
.env.example file for an example.
Makefile for more context on how this works under the hood.
If you’re going to deploy to a testnet, make sure you have testnet ETH and LINK in your wallet. You can get testnet LINK from the Chainlink Faucet.
Set Up Your
You can see in the
.env.example an example of what your
.env should look like (to deploy to a live network).
ALCHEMY_API_KEY: You can find this from getting an Alchemy account.
ETH_FROM: The address of your wallet you want to send transactions from. You must have the private key of the address you want to use loaded into your
ethsign, see above for this.
ETHERSCAN_API_KEY: For verifying contracts on Etherscan (optional).
ETH_RPC_URL: For having a default deployment network when using
Testnet and Mainnet Deployment
ALCHEMY_API_KEY in your
.env file, then run one of the following:
Counters (Automation Compatible Contract):
bash make deploy CONTRACT=Counter
bash make deploy CONTRACT=PriceFeedConsumer
Chainlink VRF Consumer:
bash make deploy CONTRACT=VRFConsumer
You can change their deployment parameters in their respective
deploy file in the
scripts folder. All the constructor arguments are created in the
./src/helper-config.sh folder. This is where you can assign different constructor arguments across networks.
# on one terminal
Then run your deploy script.
Verifying on Etherscan
After deploying your contract you can verify it on Etherscan using:
ETHERSCAN_API_KEY=<api-key> dapp verify-contract <contract_directory>/<contract>:<contract_name> <contract_address>
ETHERSCAN_API_KEY=123456765 dapp verify-contract ./src/Counter.sol:Counter 0x23456534212536435424
Check out the dapp documentation to see how verifying contracts work with DappTools.
Interacting With Your Contracts
To interact with our contracts, we use the
seth command. Let’s say we’ve deployed our
PriceFeedConsumer.sol to Kovan, and now we want to call the
getLatestPrice function. How do we do this?
ETH_RPC_URL=<YOUR_RPC_URL> seth call <YOUR_CONTRACT_ADDRESS> "getLatestPrice()"
ETH_RPC_URL=https://alchemy.io/adsfasdf seth call 0xd39F749195Ab1B4772fBB496EDAF56729ee36E55 "getLatestPrice()"
This will give us an output like
0x0000000000000000000000000000000000000000000000000000004c17b125c0 which is the hex of
This is to call transactions (not spend gas). To change the state of the blockchain (spend gas) we’d use
seth send. Let’s say we have a
VRFConsumer contract deployed, and we want to call
First, we’d need to send our contract some LINK on the Kovan chain:
ETH_RPC_URL=<YOUR_RPC_URL> ETH_FROM=<YOUR_FROM_ADDRESS> seth send <LINK_TOKEN_ADDRESS> "transfer(address,uint256)" <VRF_CONSUMER_ADDRESS> 1000000000000000000
ETH_RPC_URL=https://alchemy.io/adfasdf ETH_FROM=0x12345 seth send 0xa36085F69e2889c224210F603D836748e7dC0088 "transfer(address,uint256)" 0xa74576956E24a8Fa768723Bd5284BcBE1Ea03adA 100000000000000000
100000000000000000 = 1 LINK
Then, we could call the
ETH_RPC_URL=<YOUR_RPC_URL> ETH_FROM=<YOUR_FROM_ADDRESS> seth send <VRF_CONSUMER_ADDRESS> "getRandomNumber()"
And after a slight delay, read the result:
ETH_RPC_URL=<YOUR_RPC_URL> seth call <VRF_CONSUMER_ADDRESS> "randomResult()"
As you can see, it would be great to have these scripted in our
scripts folder. If you would like to contribute, please make a PR!
Some useful resources for this tutorial:
DappTools is an incredibly powerful application that can help you on your journey to building a game-changing dApp. We recommend checking it out, giving it a try, and seeing what you can build by leveraging Chainlink decentralized services.
Learn more about Chainlink by visiting chain.link or reading the documentation at docs.chain.link. To discuss an integration, reach out to an expert.