Forking Ethereum Mainnet: Mint Your Own Dai

There are a handful of reasons why you may want to fork Ethereum Mainnet to use on your local developer machine. Chief among them is the ability to test your smart contracts against Mainnet chain code and addresses. For example, if your smart contract interacts with external ERC20 tokens or contracts, like Dai or Compound, having a forked Mainnet chain to run your test suite against can be incredibly helpful in simplifying your workflow.
One tool, ganache-cli
, can extend off of any Ethereum node endpoint, directing new requests to itself and letting anything older pass through to the underlying node. It even has a nifty feature to let you unlock
any addresses or contracts so you can control them without needing authorization.
This is a compelling alternative to using a public testnet, like Rinkeby, or using your own self-mining developer environment. In these cases, you would have to deploy your own contracts for any existing artifacts you may be utilizing and swap the addresses in your contract.
Now, if you’re sufficiently convinced, let’s walk through forking Mainnet for development.
Step 1: Install Ganache CLI
To get started, first install ganache-cli
globally:
npm install -g ganache-cli
Once installed, the command we’re looking for is:
ganache-cli --fork NODE_URL
where NODE_URL
is the node endpoint you would like to fork, typically http://localhost:8545
. No node is running on that port yet, so let’s change that.
Step 2: Initialize an Active Ethereum Node
Running a node can be done using remote infrastructure or, ideally, by using your own machine.
Infura
Infura is great remote node service that gives you a free allowance of 100,000 requests per day. However, to access any chain data greater than 30 minutes old, you have to pay an additional $250 per month (at the time of writing). For most hobbyist developers, this price point is a deal breaker.
Ethereum Grid
Grid is a desktop app that helps you manage and launch Ethereum nodes, tools, and services. For the rest of this tutorial, we’ll use Grid to easily manage a Geth developer instance and sync a Mainnet node for ganache-cli
to fork off of. Grid will also remember our settings so it requires just one click to get our node back up and running to jump back into our testing environment.
If you don’t have Grid already, Windows, Mac, and Linux builds are available at grid.ethereum.org.
Configuring Grid and Geth
After opening Grid, click on Geth
and you will be taken to its plugin page. Download the latest version, then click on the Settings
tab. Ensure the Network
is set to Main and the Sync Mode
is set to Light. You will also want to ensure the HTTP RPC API
is set to Enabled for All Origins (*)
so ganache doesn’t have any difficulty accessing the endpoint.
Now you can toggle on Geth. You should see the network status first start looking for peers, then start syncing. After fully synchronized, we are ready to go.

Back to ganache-cli
Now we will start ganache-cli
with:
ganache-cli --fork http://localhost:8545
You should see output similar to this:

As the logs indicate, ganache-cli
generates 10 accounts with 100 ETH each for use in your tests. Further down in the terminal output, you should see that you’ve forked off of the node on http://localhost:8545
and that, on the last line, your forked node is now Listening on 127.0.0.1:8546
.

Using your new node
Now that your forked node is up and running, let’s give it a try with a test transaction. We’ll use MetaMask to visually interact with the network.
First, change MetaMask’s network to our forked client by clicking on Custom RPC
in the network dropdown and inputting http://localhost:8546
and a ChainID of 1
.


Now, you can use your already available accounts within MetaMask to interact with the forked network.
If you switch back to your terminal, you can see all the new requests that ganache-cli
is responding to:

At this point, you’re ready to develop and test Dapps on your forked network. Just make sure you’re pointing to the relevant port (8546) where appropriate — don’t accidentally test on Mainnet!
Note that if you send multiple transactions, then eventually reset the network, you will probably need to reset the nonce
for your account in MetaMask by navigating to Setting > Advanced > Reset Account
. The nonce
is the number of transactions sent from a given address for each network, and if you are changing networks like this, it can throw this number off. A wrong nonce results in rejected transactions, as it must be sequential from your last registered (or pending) transaction.
Unlocking addresses
A handy feature of ganache-cli is the --unlock
parameter, where you can unlock any address — including contract addresses! This can be useful in your test suites to get around what would otherwise be limitations.
For example, let’s take a look at getting some Dai for the new accounts ganache-cli
has generated for us. This would naturally be helpful if a smart contract we’re developing interacts with Dai. In our test suite we can interact with the contract, check that Dai balances change as necessary, etc.
Minting Dai
If you take a look at the Dai ERC20 contract on Etherscan, you can see that the contract implements a function called mint
that adds new supply to an address:
event Mint(address indexed guy, uint wad);
...
function mint(address guy, uint wad) public auth stoppable {
_balances[guy] = add(_balances[guy], wad);
_supply = add(_supply, wad);
Mint(guy, wad);
}
The contract requires auth
so not every person can mint Dai for themselves 😄, but with our awesome friend ganache-cli
we can just add the address of the contract to --unlock
so we can send a transaction to itself, minting Dai for our own accounts.
The command would look like so:
ganache-cli --fork NODE_URL --unlock 0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359
The next challenge is that the address doesn’t have any ether, so you cannot actually execute a transaction yet.
Usually we could just send some ether to the address, however the contract doesn’t have a default payable
function. It therefore can’t accept any incoming ether.
However, there is a loophole we can use! It turns out you can send ether to any address by setting the intended address as the receipt of a contract selfdestruct
(read more about that here if you would like). A contract called ForceSend.sol does exactly that.
All in all, this is what it would look like to mint 100 Dai for each of our first 5 accounts in a Truffle test suite on our forked and unlocked Mainnet:
Want to test or play around with this code? Check out the starter repo.
Thanks!
Hopefully this tutorial helps simplify your development workflow. Thank you for following along and also for checking out Ethereum Grid. If you’d like to learn more about Grid, check out other articles in this publication and stay tuned for the video of our Devcon 5 talk. If you gave it a spin, we appreciate feedback and feature requests.