> ## 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.

# State sync

> How state sync works in Polygon PoS, allowing Ethereum contract state to be reflected in Bor through the StateSender and StateReceiver contracts.

State sync is the mechanism by which contract state on Ethereum is propagated to the Bor chain. It allows dApps on Polygon PoS to read and react to events that originate on Ethereum.

## How state sync works

State transfer from Ethereum to Bor happens through a system call:

1. A contract on Ethereum calls `syncState` on the `StateSender.sol` contract, emitting a `StateSynced` event.
2. Heimdall validators listen for `StateSynced` events. One validator sends a state-sync transaction to Heimdall.
3. Once the transaction is included in a Heimdall block, it is added to the pending state-sync list.
4. After every sprint on Bor (currently 16 blocks), the Bor node fetches pending state-sync records from Heimdall via API.
5. Bor commits these records at the start of each sprint by calling `onStateReceive` on the target contract. This is a system call from address `2^160-2`.

The receiver contract on Bor must implement `IStateReceiver`. The `onStateReceive` function can only be called by `StateReceiver.sol` at address `0x0000000000000000000000000000000000001001`.

## State sender contract

Source: [StateSender.sol](https://github.com/0xPolygon/pos-contracts/blob/develop/contracts/root/stateSyncer/StateSender.sol)

The `StateSender` contract on Ethereum exposes a `syncState` function:

```jsx theme={null}
contract StateSender {
 /**
  * Emits `stateSynced` events to start sync process on Ethereum chain
  * @param receiver    Target contract on Bor chain
  * @param data        Data to send
  */
 function syncState (
  address receiver,
  bytes calldata data
 ) external;
}
```

Calling `syncState` emits the following event:

```jsx theme={null}
/**
 * Emits `stateSynced` events to start sync process on Ethereum chain
 * @param id                  State id
 * @param contractAddress     Target contract address on Bor
 * @param data                Data to send to Bor chain for Target contract address
 */
event StateSynced (
 uint256 indexed id,
 address indexed contractAddress,
 bytes data
);
```

Once the `StateSynced` event is emitted, Heimdall listens for it. After 2/3+ validators agree, the state-sync record is added to Heimdall state. Bor fetches and applies it at the start of the next sprint.

## State receiver interface on Bor

The target contract on Bor must implement the following interface:

```jsx theme={null}
// IStateReceiver represents interface to receive state
interface IStateReceiver {
  function onStateReceive(uint256 stateId, bytes calldata data) external;
}
```

Only `StateReceiver.sol` at address `0x0000000000000000000000000000000000001001` is permitted to call `onStateReceive` on target contracts.

## System calls

The state sync commit on Bor uses a system call. Only the system address `2^160-2` can make a system call. Bor calls it internally with the system address as `msg.sender`, which changes contract state and updates the state root for the block, without requiring a user-initiated transaction. This is inspired by [EIP-210](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-210.md).

## State-sync logs and Bor block receipts

Events emitted by system calls are handled differently from normal logs. Bor produces a synthetic transaction and receipt for each state-sync event, so clients can query these events through standard Ethereum JSON-RPC methods. The transaction hash is derived from:

```jsx theme={null}
keccak256("matic-bor-receipt-" + block number + block hash)
```

This synthetic transaction does not affect consensus logic. `eth_getBlockByNumber`, `eth_getTransactionReceipt`, and `eth_getLogs` include state-sync logs from the derived transaction. Note that the block bloom filter does not include state-sync log entries, and the derived transaction is not included in `transactionRoot` or `receiptRoot`.
