Skip to main content
This doc is currently undergoing revision, and the instructions provided may not be up to date. Stay tuned for updates!
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.

Implementation

Create the root chain and child chain contracts. The function that performs the state change must also emit an event whose parameters include the data to transfer.
Child contract
contract Child {

    event Data(address indexed from, bytes bytes_data);

    uint256 public data;

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

}
Pass this 0x1470E07a6dD1D11eAE439Acaa6971C941C9EF48f as the value for _predicate in the root contract constructor.
Root contract
contract Root {

    address public predicate;
    constructor(address _predicate) public{
        predicate=_predicate;
    }

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

    uint256 public data;

    function setData(bytes memory bytes_data) public onlyPredicate{
        data = abi.decode(bytes_data,(uint256));
    }

}
Once the child and root contract is deployed on the Polygon and Ethereum chain respectively, these contracts have to be mapped using the PoS bridge. This mapping ensures that a connection is maintained between these two contracts across the chains. For doing this mapping,the Polygon team can be reached on Discord. One important thing to note is that in the root contract, there is a onlyPredicate modifier. It is recommended to use this modifier always because it ensures that only the predicate contract makes the state change on the root contract. The predicate contract is a special contract that triggers the root contract only when the transaction that happened on the Polygon PoS chain is verified by the RootChainManager on Ethereum chain. This ensures secure change of state on the root contract. For testing the above implementation, we can create a transaction on the Polygon chain by calling the setData function of the child contract. We need to wait at this point for the checkpoint to be completed. The checkpoint inclusion can be checked using this script. Once checkpoint is completed, call the exit function of the RootChainManager using matic.js SDK.
const txHash =
  "0xc094de3b7abd29f23a23549d9484e9c6bddb2542e2cc0aa605221cb55548951c";

const logEventSignature =
  "0x93f3e547dcb3ce9c356bb293f12e44f70fc24105d675b782bd639333aab70df7";

const execute = async () => {
  try {
    const tx = await maticPOSClient.posRootChainManager.exit(
      txHash,
      logEventSignature
    );
    console.log(tx.transactionHash); // eslint-disable-line
  } catch (e) {
    console.error(e); // eslint-disable-line
  }
};
As shown in the above screenshot, the txHash is the transaction hash of the transaction that happened on the child contract deployed on Polygon chain. The logEventSignature is the keccack-256 hash of the Data event. This is the same hash that we have included in the predicate contract. All the contract code used for this tutorial and the exit script can be found here Once the exit script is completed, the root contract on Ethereum chain can be queried to verify if the value of the variable data that was set in child contract has also been reflected in the data variable of the root contract.