How To Recover Celo Funds Sent To Ethereum Address
Celo is a new project for digital payments, which issued CELO coins available for purchase on exchanges like Bitfinex. It shares a lot of tooling with Ethereum and currently (Aug 2020) uses addresses which are fully compatible with Ethereum network. So it is pretty easy to accidentally send CELO funds to an Ethereum address, such as Metamask generated one. Since CELO runs independent network, the funds become inaccessible.
CELO uses BIP-32 seed generation for HD wallet using path m/44'/52752'/0'/0, while Ethereum uses m/44'/60'/0'/0 for its wallet, where the 3rd value in the path (52752') denotes CELO coin id. Thus it is impossible to take a mnemonic phrase used to generate Ethereum accounts, and generate same account hierarchy for CELO with matching address. However if we manage to create CELO wallet with such address by other means, it becomes “fully compatible” with CELO network.
To recover funds one can import Ethereum account into CELO network by using its address private key. At this point such account joins CELO network and funds can be transferred to a standard CELO wallet generated from a mnemonic set of secret words words or back the the exchange.
The import however requires some deliberate setup of CELO node and celocli. In particular we need to import private key into the same location where private key associated with running CELO node is located. So the sequence of steps becomes:
- Set up account address to run CELO node
- Run CELO node
- Import Metamask private key using CELO geth, such that it ends up in the same keystore as account address in step 1.
- Transfer funds using celocli
For the first 2 steps we can follow CELO team instruction to set up the full node
# pull node image
export CELO_IMAGE=us.gcr.io/celo-org/celo-node:mainnet
export NETWORK_ID=42220
docker pull $CELO_IMAGEmkdir celo-data-dir
cd celo-data-dir# create account associated with the node
docker run -v $PWD:/root/.celo --rm -it $CELO_IMAGE account new
export CELO_ACCOUNT_ADDRESS=<YOUR-ACCOUNT-ADDRESS># initialize CELO node
run --rm -it -v $PWD:/root/.celo $CELO_IMAGE init /celo/genesis.json
export BOOTNODE_ENODES=$(docker run --rm --entrypoint cat $CELO_IMAGE /celo/bootnodes)# start the node
# note an additional flag --allow-insecure-unlock needed
# to send funds using celocli via this node
docker run --name celo-fullnode -d --restart unless-stopped -p 127.0.0.1:8545:8545 -p 127.0.0.1:8546:8546 -p 30303:30303 -p 30303:30303/udp -v $PWD:/root/.celo $CELO_IMAGE --verbosity 3 --networkid $NETWORK_ID --syncmode full --rpc --rpcaddr 0.0.0.0 --rpcapi eth,net,web3,debug,admin,personal --light.serve 90 --light.maxpeers 1000 --maxpeers 1100 --etherbase $CELO_ACCOUNT_ADDRESS --bootnodes $BOOTNODE_ENODES --nousb --allow-insecure-unlock
At this point node is running and we can check its readiness using celocli
# install celocli
npm install @celo/celocli# check if node is synchronized
./node_modules/.bin/celocli node:synced
True
The node is running and we can import Metamask private key
# save metamask pk into a file
echo <metamask_pk> > metamask-pk.dat
# import it with password protection in password.txt
docker run -v `pwd`:/root/.celo us.gcr.io/celo-org/celo-node:mainnet account import /root/.celo/metamask-pk.dat -password /root/.celo/password.txt
At this point we can check balance:
/node_modules/.bin/celocli account:balance <your account>All balances expressed in units of 10^-18.CELO: 10000000000000000000# Unlock the account
./node_modules/.bin/celocli account:unlock <address>
And send it to CELO wallet address or back to exchange
./node_modules/.bin/celocli transfer:celo --from <your metamask address> --to <destination address> --value 10000000000000000000
That’s it!