Running your tx locally before sending it to mainnet

Carlos Sessa
4 min readNov 22, 2020

Hello! I wanted to write a small guide on how to run a tx locally,
before running it in mainnet. Why? Because you might get an unpleasant surprise.

Today, with the Pickle hack, I saw a bunch of Twitter messages asking everyone to withdraw from their jars, but was it worth it? Here’s an example of the pie on the face you might get:

https://etherscan.io/tx/0xaa2c3c84676ad5b50ce8368a8d76875e7bf728726075fafc22db4675db8a4f2e

A user called withdrawAll() with around 7.1k pDAI and got back 1.23 DAI after paying 3.55USD in fees.

Since I had DAI deposited in pDAI, I went through the process of withdrawing my funds from the platform. Since the UI was dead, there were two options for me, etherscan or command line with Brownie.

What’s Brownie?

Brownie is a Python-based development and testing framework for smart contracts targeting the EVM

Don’t let that nerdy description scare you. The non-dev description should be:

A command-line tool to interact with the Ethereum blockchain…
and test random transaction in a local fork

Installation

This will be 80% of the work. Setting the development environment is a PITA but trust me, it’s worth it. There are three things you will need:

1. Installing Brownie dependencies

Brownie depends on python3 and ganache-cli.
You will need to install python3 on your computer and https://github.com/trufflesuite/ganache-cli

2. Install Brownie

Follow the instructions here: https://eth-brownie.readthedocs.io/en/stable/install.html

3. Get an Infura key
This will be our node. You can get a token from https://infura.io/

In short, Brownie is the python interface, which talks to ganache-cli and ganache-cli talks to the ethereum network through infura.

Full description of the installation process is out of the scope but feel free to ask how to do it or if you get stuck.

To run Brownie in a fork, we start the console with the following command:

$ brownie console --network mainnet-fork

That command will go to Infura and fork from the last block.
All the changes we apply to the chain from that console will stay on our computer and we can do whatever we want.

Let’s go through the example of testing what would happen if a whale withdraws. If we check for the pDAI contract holders (https://etherscan.io/token/0x6949Bb624E8e8A90F87cD2058139fcd77D2F3F87#balances) we can use as an example a wallet which at the moment has 55% of funds: 0x777999be819ffecee44a995560a9d0e97780a30c

First step, let’s grab the pDAI contract:

pdai = Contract.from_explorer(“0x6949Bb624E8e8A90F87cD2058139fcd77D2F3F87”)

You will notice that now you can use the pdai variable to call contract methods. For example, you can run pdai.available() to see how much DAI the strategy can borrow.

You also get a fancy autocomplete!

We would need to divide the result by 1e18 because of DAI decimals

>>> pdai.available()/1e18
51200.58944350616

Next, let’s get the DAI token contract. We will get it from pDAI itself.

dai = Contract.from_explorer(pdai.token())

Now that we have all the contracts we need, let’s impersonate the whale.
Notice that you can do the following command with your own address.

whale = accounts.at(“0x777999be819ffecee44a995560a9d0e97780a30c”, force=True)

That force=True means that we will own that address and we have full control over it. Yes, you can force 0x0000000000000000000000000000000000000000 and feel rich. Let’s see the whale’s balance:

>>> pdai.balanceOf(whale)/1e18
174359214.11612254
>>> dai.balanceOf(whale)/1e18
0.0

That’s 174M pdai! Now, let’s send a tx as if the whale were to withdraw all.

>>> pdai.withdrawAll({‘from’: whale})
Transaction sent: 0xb4be376fc86ad56b514d8fbaaef05a1a457d8448b1387c98659e9c7a83707fba
Gas price: 0.0 gwei Gas limit: 12000000 Nonce: 8646
PickleJar.withdrawAll confirmed — Block: 11304646 Gas used: 91957 (0.77%)
<Transaction ‘0xb4be376fc86ad56b514d8fbaaef05a1a457d8448b1387c98659e9c7a83707fba’>

Since we are in the command-line we need to tell Brownie who is sending the tx. If you check in etherscan, you will notice that withdrawAll() doesn’t have parameters.

Finally, let’s check balances:

>>> dai.balanceOf(whale)/1e18
30000.0
>>> pdai.balanceOf(whale)/1e18
0.0

Worth it for the whale? perhaps. Is it worth it for you? Give it a try!

When I went through these calls with my own address, I noticed that I was only going to get 10 cents. Since those cents would not cover the gas cost, I decided to keep my pDAI.

Today is just another reminder of:

Don’t risk money you can’t afford to lose

I sincerely hope you didn’t lose too much and use this as a learning experience. Have a nice day!

--

--