Skip to main content

State Transfer


Polygon validators continuously monitor a contract on Ethereum chain called StateSender. Each time a registered contract on Ethereum chain calls this contract, it emits an event. Using this event Polygon validators relay the data to another contract on Polygon chain. This StateSync mechanism is used to send data from Ethereum to Polygon.

Polygon validators also periodically submit a hash of all transactions on the Polygon chain to the Ethereum chain. This Checkpoint can be used to verify any transaction that happened on Polygon. Once a transaction is verified to have happened on the Polygon chain, an action can be taken accordingly on Ethereum.

These 2 mechanisms can be used together to enable two-way data (state) transfer between Ethereum and Polygon. To abstract out all these interactions, you can directly inherit our FxBaseRootTunnel (on Ethereum) and FxBaseChildTunnel (on Polygon) contracts.

Root Tunnel Contract

Use the FxBaseRootTunnel contract from here. This contract gives access to the following functions:

  • function _processMessageFromChild(bytes memory data): This is a virtual function that needs to be implemented in the contract which inherits it to handle data being sent from ChildTunnel.
  • _sendMessageToChild(bytes memory message): This function can be called internally with any bytes data as a message. This data will be sent as it is to the child tunnel.
  • receiveMessage(bytes memory inputData): This function needs to be called to receive the message emitted by ChildTunnel. The proof of transaction needs to be provided as calldata. An example script to generate proof using matic.js is included below.

Child Tunnel Contract

Use the FxBaseChildTunnel contract from here. This contract gives access to following functions:

  • function _processMessageFromRoot(uint256 stateId, address sender, bytes memory data): This is a virtual function that needs to implement the logic to handle messages sent from the RootTunnel.
  • function _sendMessageToRoot(bytes memory message): This function can be called internally to send any bytes message to the root tunnel.


  • You need to inherit FxBaseRootTunnel contract in your root contract on Ethereum. As an example, you can follow this contract . Similarly, inherit FxBaseChildTunnel contract in your child on Polygon. Follow this contract as an example.
  • While deploying your root contract on Goerli testnet, pass the address of _checkpointManager as 0x2890bA17EfE978480615e330ecB65333b880928e and _fxRoot as 0x3d1d3E34f7fB6D26245E6640E1c50710eFFf15bA . For Ethereum mainnet _checkpointManager is 0x86e4dc95c7fbdbf52e33d563bbdb00823894c287 and _fxRoot is 0xfe5e5D361b2ad62c541bAb87C45a0B9B018389a2.
  • For deploying the child contract on Mumbai testnet, pass 0xCf73231F28B7331BBe3124B907840A94851f9f11 as _fxChild in constructor. For Polygon mainnet, _fxChild will be 0x8397259c983751DAf40400790063935a11afa28a .
  • call setFxChildTunnel on deployed root tunnel with the address of child tunnel (E.g: )
  • call setFxRootTunnel on deployed child tunnel with address of root tunnel (E.g: )

Example contracts of state transfer bridge

State transfer from Ethereum to Polygon

State transfer from Polygon to Ethereum

// npm i @maticnetwork/maticjs
// for goerli - mumbai testnet
const getPOSClient = (network = 'testnet', version = 'mumbai') => {
const posClient = new POSClient()
return posClient.init({
log: true,
network: network,
version: version,
child: {
parent: {
posClient.exitUtil.buildPayloadForExit(<burntxhash>,<event signature>)