Skip to main content
Polygon PoS provides several contracts for passing data between Ethereum (L1) and Polygon (L2). They serve different purposes and operate at different levels of abstraction. The right choice depends on what you are transferring and in which direction.

Ethereum to Polygon (L1 to L2)

Data flows from Ethereum to Polygon via the state sync mechanism. A contract on Ethereum calls syncState on the StateSender contract, which emits a StateSynced event. Heimdall validators relay this event to Bor, which calls onStateReceive on the target contract on Polygon within a single sprint (approximately 16 blocks, or a few minutes). This mechanism is used internally by both the PoS token bridge and FxPortal. You can also use it directly for arbitrary data, subject to the registration requirement described below. For a step-by-step implementation, see Ethereum to PoS.

Registration requirement

Sender/receiver pairs must be registered with StateSender before state sync will relay events between them. This registration authorizes the pair: Heimdall only processes StateSynced events from registered sender contracts targeting registered receiver contracts. Registration is managed by the Polygon team. Contact the team on Discord or via the mapping request form to register a new pair.
If you need arbitrary message passing without registering a custom pair, FxPortal provides a pre-registered sender/receiver abstraction. See the FxPortal contracts below.

Security in receiver contracts

The onStateReceive function on Polygon is called by the StateReceiver system contract at address 0x0000000000000000000000000000000000001001. Always verify msg.sender against this address in your receiver implementation. Without this check, any address on Polygon can call onStateReceive directly and inject arbitrary data. See the state sync architecture docs for a full description of how state sync works.

Polygon to Ethereum (L2 to L1)

Data flows from Polygon back to Ethereum via the checkpoint and exit mechanism. There is no continuous message relay in this direction. Instead:
  1. A transaction on Polygon emits an event containing the data to transfer.
  2. The transaction is included in a Polygon checkpoint, which is committed to Ethereum roughly every 30 minutes.
  3. After the checkpoint is finalized on Ethereum, anyone can submit an exit proof to RootChainManager on Ethereum to trigger the corresponding state change on the root contract.
This is how the PoS bridge handles withdrawals: tokens are burned on Polygon, and after checkpoint, the lock is released on Ethereum. The same pattern works for arbitrary data. For a step-by-step implementation, see PoS to Ethereum.

Choosing the right approach

NeedRecommended approach
Bridge a standard ERC-20, ERC-721, or ERC-1155 tokenSubmit a mapping request and use the PoS bridge contracts
Send arbitrary data from Ethereum to Polygon without custom registrationUse FxPortal (FxRoot / FxChild)
Send arbitrary data from Ethereum to Polygon with a custom registered pairRaw state sync via StateSender
Send data from Polygon back to EthereumCheckpoint and exit via RootChainManager
If you are building fee collection or settlement infrastructure that bridges tokens from Polygon back to Ethereum from a smart contract, use the PoS bridge withdrawal path: call withdraw on the child ERC-20 contract on Polygon to burn tokens, then after checkpoint, call exit on RootChainManager on Ethereum to release the funds to your target address.

Contract reference

The following contracts are used for L1-L2 messaging on mainnet. Source addresses are from the canonical network config.

State sync

These are the low-level contracts that underpin all L1-to-L2 messaging on Polygon PoS.
ContractNetworkAddressPurpose
StateSenderEthereum0x28e4F3a7f651294B9564800b2D01f35189A5bFbEEntry point for L1→L2 messages. Registered sender contracts call syncState here.
StateReceiverPolygon0x0000000000000000000000000000000000001001Genesis contract that delivers state sync messages on Polygon by calling onStateReceive on the target contract.

FxPortal

FxPortal is Polygon’s pre-registered messaging layer built on top of state sync. FxRoot is already registered as a sender in StateSender, and FxChild is its registered receiver on Polygon. You can inherit from FxBaseRootTunnel and FxBaseChildTunnel to build bidirectional messaging without needing custom registration.
ContractNetworkAddressPurpose
FxRootEthereum0xfe5e5D361b2ad62c541bAb87C45a0B9B018389a2Ethereum-side entry point for FxPortal. Calls syncState on StateSender.
FxChildPolygon0x8397259c983751DAf40400790063935a11afa28aPolygon-side receiver for FxPortal. Called by StateReceiver and routes messages to child tunnel contracts.
FxERC20RootTunnelEthereum0x0cc2caed31490b546c741bd93dbba8ab387f7f2cFxPortal tunnel for bridging ERC-20 tokens via FxRoot.
FxERC721RootTunnelEthereum0xca1f5ec720eCdA31bE3d80BD3ef4686cBb07eb4DFxPortal tunnel for bridging ERC-721 tokens via FxRoot.
FxERC20ChildTunnelPolygon0xd531Cf2142D9b9Dc8b077dF3c4E93B46E7Cf879aPolygon-side counterpart to FxERC20RootTunnel.
FxERC721ChildTunnelPolygon0x2b4732e448b3023131a7b25046b3A5EF50CfCf71Polygon-side counterpart to FxERC721RootTunnel.

PoS token bridge

These contracts handle token deposits and withdrawals through the official PoS bridge. Use these when bridging mapped ERC-20, ERC-721, or ERC-1155 tokens rather than arbitrary data.
ContractNetworkAddressPurpose
RootChainManagerProxyEthereum0xA0c68C638235ee32657e8f720a23ceC1bFc77C77Main entry point for PoS token bridge on Ethereum. Call depositFor to deposit tokens and exit to finalize withdrawals after checkpoint.
ChildChainManagerProxyPolygon0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aaPolygon-side manager. Mints tokens on deposit and processes burns on withdrawal.
ERC20PredicateProxyEthereum0x40ec5B33f54e0E8A33A975908C5BA1c14e5BbbDfLocks ERC-20 tokens on Ethereum on deposit; releases them on exit.
ERC721PredicateProxyEthereum0xE6F45376f64e1F568BD1404C155e5fFD2F80F7ADLocks ERC-721 tokens on Ethereum on deposit; releases them on exit.
ERC1155PredicateProxyEthereum0x0B9020d4E32990D67559b1317c7BF0C15D6EB88fLocks ERC-1155 tokens on Ethereum on deposit; releases them on exit.