Forking Ethereum Mainnet: Mint Your Own Dai

Ryan Ghods
Nov 5 · 6 min read

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.

Philipp and Everton presenting Grid at Devon V

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.

Mainnet Syncing Progress within Ethereum Grid

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.

The forked chain client is available on port 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.

Connect to a Custom RPC network
Provide the URL of the forked node on port 8546

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.

Ethereum Grid

Ethereum tooling made super-easy

Thanks to Marc Garreau

Ryan Ghods

Written by

Code, UX, and Coffee.

Ethereum Grid

Ethereum tooling made super-easy