How to interact with Ethereum’s mainnet in a development environment with Ganache

Sam Richards
Aug 8, 2019 · 2 min read
Ganache and mainnet… a true love story

If you’re writing Ethereum smart contracts that interact with external contracts, e.g. the MakerDAO and Uniswap protocols, you’ll want to test those interactions in your local environment to ensure they execute as expected.

The painful way (with Truffle and Ganache)

You could spin up a local Ganache chain, manually copy and paste the verified contracts from Etherscan, then deploy the contracts and seed them with data in Truffle migration scripts. With a simple protocol like Uniswap, this is feasible but still requires multiple steps. Here are the transactions you’d need to execute before your contract can interact with Uniswap’s Dai exchange:

  1. Deploy the UniswapExchange contract
  2. Deploy the UniswapFactory contract
  3. Initialize the UniswapFactory (with the UniswapExchange address)
  4. Deploy the Dai ERC20 token contract
  5. Deploy the Dai UniswapExchange contract (using the Dai address)
  6. Approve the Dai UniswapExchange contract to transfer Dai
  7. Add liquidity to the Dai UniswapExchange contract

Here’s how that looks within a Truffle migration script (full code here):

// Deploy Dai token
await deployer.deploy(DaiToken, name, symbol, decimals, supply);
const dai = await DaiToken.at(DaiToken.address);
// Deploy UniswapExchange (exchange template)
await deployer.deploy(UniswapExchange);
// Deploy & initialize UniswapFactory
await deployer.deploy(UniswapFactory);
const factoryInstance = await UniswapFactory.at(UniswapFactory.address);
await factoryInstance.initializeFactory(UniswapExchange.address);
// Deploy UniswapExchange for Dai token
await factoryInstance.createExchange(dai.address);
// Approve Dai UniswapExchange contract to transfer Dai
const daiExchangeAddress = await factoryInstance.getExchange(dai.address);
await dai.approve(daiExchangeAddress);
// Add liquidity to Dai UniswapExchange (5 ETH, 10000 DAI)
const daiExchangeInstance = await UniswapExchange.at(daiExchangeAddress);
const minLiquidity = 0;
const maxTokens = 10000;
const deadline = Math.floor(Date.now() / 1000) + 300;
await daiExchangeInstance.addLiquidity(minLiquidity, maxTokens, deadline, { value: 5000000000000000000 });

Now imagine the setup required for a complex protocol like MakerDAO, which consists of over 40 smart contracts. It’s brutal. Check out this 150-line migration script if you’re curious.

Note: MakerDAO did create a test chain repo to make this easier but I still found it difficult to integrate into a Truffle project.

The easy way (with Truffle and Ganache)

Ganache provides an immensely powerful forking feature that lets you point to an endpoint (i.e. Geth or Infura) and an optional block number to “fork” the Ethereum mainnet into your local chain at a given block. This allows you to interact with mainnet contracts and data in a deterministic way.

The easiest way is to create an Infura project, then run:

ganache-cli --fork https://mainnet.infura.io/v3/{infura_project_id}@{block_number}

Boom. You’re up and running. Ganache (thankfully) won’t download the entire mainnet blockchain, it will only make calls to your endpoint node for data when necessary. Now you can configure your Truffle project to point at this Ganache instance and interact with those external contracts within Truffle’s console or even in your test suite.

Note: you’ll still need to set up interfaces to the external contracts you want to interact with.

Thoughts? Questions? Please drop a comment below.

Sam Richards

Written by

Web developer @ ethereum.org

More From Medium

More from Sam Richards

Related reads

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade