Ether Deposit and Withdraw Guide

Quick Summary

This section deals with the flow of transactions from the Ethereum to the Polygon chain, but this time we're going by way of the powerful Polygon Contracts. In this section, we'll learn how to instantiate the contracts, deposit, burn, and exit. Let's go.

High Level Flow

Depositing Ether

  • Make the depositEtherFor call on the RootChainManager and send the ether asset.

Withdrawing Ether

  • Burn the tokens on the Polygon chain.
  • Call the exit function and make sure to submit the transaction proof of burn hash. This call is to be made after the checkpoint is submitted for the block containing burn transaction


Instantiate the contracts

These are the contracts exposed here

const mainWeb3 = new Web3(mainProvider)
const maticWeb3 = new Web3(maticProvider)
const rootChainManagerContract = new mainWeb3.eth.Contract(rootChainManagerABI, rootChainManagerAddress)
const childTokenContract = new maticWeb3(childTokenABI, childTokenAddress)


Next step is to call the depositEtherFor function of the RootChainManager contract. This function takes one argument, user, which is the address of the user that will receive the deposit on the Polygon chain. The amount of ether to be deposited is sent as the value of the transaction.

await rootChainManagerContract.methods
.send({ from: userAddress, value: amount })


Ether is interpreted on the Polygon chain as an ERC20 token, so its withdrawal process is pretty much the same as ERC20 withdrawal. To burn a token, call the withdraw function on the childTokenContract and pass a parameter, amount, indicating the number of tokens to be burned. Proof of burn need to be submitted at the exit step so make sure to store the transactionHash.

This is what the withdraw method looks like.

const burnTx = await childTokenContract.methods
.send({ from: userAddress })
const burnTxHash = burnTx.transactionHash


The exit function is what is called on the RootChainManager contract to unlock and receive tokens back from the EtherPredicate. It's important that you wait for the checkpoint containing the burn transaction to be submitted before calling this function. The exit function takes a single argument, in the form of bytes, that is the proof of burn for the transaction.

The proof of burn in itself is generated by RLP encoding the following fields:

  • headerNumber - Checkpoint header block number containing the burn transaction
  • blockProof - Proof that the block header (in the child chain) is a leaf in the submitted merkle root
  • blockNumber - Block number containing the burn transaction on child chain
  • blockTime - Burn transaction block time
  • txRoot - Transactions root of block
  • receiptRoot - Receipts root of block
  • receipt - Receipt of the burn transaction
  • receiptProof - Merkle proof of the burn receipt
  • branchMask - 32 bits denoting the path of receipt in merkle patricia tree
  • receiptLogIndex - Log Index to read from the receipt

Generating all this information manually has historically proven to be tricky, so we advise you use the matic.js SDK. If you're still interested in sending the transaction manually, please pass encodeAbi as true in the options object to get raw call data.

const exitCalldata = await maticPOSClient
.exitERC20(burnTxHash, { from, encodeAbi: true })

and then send this call data to the RootChainManager

await mainWeb3.eth.sendTransaction({
from: userAddress,
to: rootChainManagerAddress,