How to interact with Ethereum’s mainnet in a development environment with Ganache
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.
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:
- Deploy the UniswapExchange contract
- Deploy the UniswapFactory contract
- Initialize the UniswapFactory (with the UniswapExchange address)
- Deploy the Dai ERC20 token contract
- Deploy the Dai UniswapExchange contract (using the Dai address)
- Approve the Dai UniswapExchange contract to transfer Dai
- 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, );
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.
Ganache provides an immensely powerful forking feature (currently only available on the cli), which will essentially 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/@
Boom. You’re up and running. Ganache (thankfully) won’t pull down the entire mainnet, it will only make calls to Infura’s node for data when necessary. Now you can configure your Truffle 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.
Published at Thu, 08 Aug 2019 03:43:10 +0000
{flickr|100|campaign}
