naser safari
2 min readDec 3, 2021

--

How we refunded our ETH programmatically from a public address that we didn’t have the private key for

We developed a smart contract and deployed and tested it successfully on both BSC and Polygon networks, then we decided to burn some ETH and try it on mainnet Ethereum, after all it was tested on two networks, what could go wrong?!

So we set up our dApp to use mainnet and tried it by calling our smart contract function and passing it 0.1 ETH, and we got a success message and just then realized that we’ve not deployed the contract yet!

As you know, EVM does not check the existence of a contract prior to calling it, so we ended up

with having 0.1 ETH locked in a public address that we didn’t have the corresponding private key.

Lucky for us, all was not lost, the public address wasn’t a random address, it was where our contract was supposed to deployed on the mainnet, because we made sure our contract address would be similar by deploying it with the same owner and the same nonce for the transaction in different networks.

So is it possible to refund the balance without having the corresponding private key? A common and popular answer is NO.

But I’m going to explain how it’s possible to refund the balance of the special public address without knowing the corresponding private key.

These steps are used to reproduce the issue on the testnet and solve it:

1- Calling getContractAddress of ethers/lib/utils

The future address is a special address, not because of the getContractAddress function, it’s a very simple function that uses account address and nonce to calculate an address:

I called it future address because when we use accountA to deploy a new contract, EVM assigns this address to the contract.

2- Send ETH to the future address by accountB

by using this simple piece of code, you can send ETH to the future address to simulate the losing ETH issue.

3- Deploy a simple contract by just one withdrawal function by using accountA

Now let’s refund the ETH without having the private key. By deploying the contract with the same address and nonce, EVM will assign the same address as the future address to the contract.

4- Call the withdrawal function to retrieve your ETH

Now you can simply call the contract withdrawal function to retrieve your ETH. I used hardhat to create the sample project, so the function call would be as simple as below:

5- Have fun :)

The source code to check the steps on the testnet could be found here:

https://github.com/nsafari/refund_balance

--

--

naser safari

A self-motivated with +14 years of experience in delivering high efficient solutions for diverse industries complicated scenarios.