> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polygon.technology/llms.txt
> Use this file to discover all available pages before exploring further.

# PoS to Ethereum

> Deploy child and root contracts to transfer data from Polygon PoS back to Ethereum using checkpoints and the RootChainManager.

This guide demonstrates transferring a `uint256` value from Polygon PoS to Ethereum. The same approach applies to any data type: encode the data as bytes, emit it from the child contract, then decode it in the root contract after checkpoint verification. For background on the checkpoint and predicate mechanism, see the [state sync architecture docs](/pos/architecture/bor/state-sync/).

<Warning title="Example code only">
  The contracts in this guide are simplified illustrations. Do not deploy them to production without a thorough security review and audit appropriate for your use case.
</Warning>

## Implementation

<Steps>
  ### Deploy contracts

  Create the child contract on Polygon PoS and the root contract on Ethereum. The function that performs the state change must emit an event whose parameters include the data to transfer.

  <CodeGroup>
    ```solidity Child.sol theme={null}
    pragma solidity ^0.8.0;

    contract Child {
        event Data(address indexed from, bytes bytesData);

        uint256 public data;

        function setData(bytes memory bytesData) public {
            data = abi.decode(bytesData, (uint256));
            emit Data(msg.sender, bytesData);
        }
    }
    ```

    ```solidity Root.sol theme={null}
    pragma solidity ^0.8.0;

    contract Root {
        address public predicate;

        constructor(address _predicate) {
            predicate = _predicate;
        }

        modifier onlyPredicate() {
            require(msg.sender == predicate, "unauthorized");
            _;
        }

        uint256 public data;

        function setData(bytes memory bytesData) public onlyPredicate {
            data = abi.decode(bytesData, (uint256));
        }
    }
    ```
  </CodeGroup>

  Pass `0x1470E07a6dD1D11eAE439Acaa6971C941C9EF48f` as the `_predicate` value in the `Root` constructor. The `onlyPredicate` modifier ensures that only the predicate contract can update state on the root contract. The predicate is invoked by `RootChainManager` on Ethereum after it verifies the transaction against a Polygon checkpoint, guaranteeing state changes on Ethereum reflect verified Polygon activity.

  ### Map your contracts

  Once both contracts are deployed, submit a mapping request so the PoS bridge recognizes the child/root pair. See the [submit a mapping request guide](/pos/how-to/bridging/ethereum-polygon/submit-mapping-request/) for steps.

  <Note>
    Already working with a widely used token? The [Polygon Portal](/tools/wallets/portal/) lists tokens that are already mapped and available for bridging without a new mapping request.
  </Note>

  ### Initiate a transfer on Polygon

  Call `setData` on the child contract with the encoded value you want to transfer. Wait for the transaction to be included in a Polygon checkpoint. Checkpoints are submitted to Ethereum roughly every 30 minutes.

  You can verify checkpoint inclusion using the [Polygon checkpoint tracker](https://github.com/rahuldamodar94/matic-learn-pos/blob/transfer-matic-ethereum/script/check-checkpoint.js) or by polling the `RootChainManager` on Ethereum.

  ### Exit on Ethereum

  After the checkpoint is confirmed, call `exit` on `RootChainManager` on Ethereum to finalize the transfer. You need the transaction hash of the `setData` call on Polygon and the keccak-256 hash of the `Data` event signature.

  The `logEventSignature` for the `Data(address,bytes)` event is:

  ```
  0x93f3e547dcb3ce9c356bb293f12e44f70fc24105d675b782bd639333aab70df7
  ```

  Using `matic.js`:

  ```javascript theme={null}
  import { POSClient, use } from "@maticnetwork/maticjs";

  const client = new POSClient();
  await client.init({ network: "mainnet", version: "v1" });

  const txHash = "0x<YOUR_POLYGON_TX_HASH>";
  const logEventSignature = "0x93f3e547dcb3ce9c356bb293f12e44f70fc24105d675b782bd639333aab70df7";

  const tx = await client.exitUtil.buildPayloadForExit(txHash, logEventSignature, false);
  ```

  Alternatively, call `exit(bytes calldata inputData)` directly on `RootChainManager` at `0xA0c68C638235ee32657e8f720a23ceC1bfc77C77` on Ethereum mainnet, constructing the proof payload from the burn receipt.

  Once the exit transaction is confirmed, query the `data` variable on the root contract to verify the value has been reflected on Ethereum.
</Steps>

The full contract source and exit script for this example are available in the [matic-learn-pos repository](https://github.com/rahuldamodar94/matic-learn-pos/tree/transfer-matic-ethereum).
