Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Smart contract for decoding State Sync data from Ethereum to Matic
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;
contract Decoder {
bytes32 public constant DEPOSIT = keccak256("DEPOSIT");
bytes32 public constant MAP_TOKEN = keccak256("MAP_TOKEN");
enum SyncType {Deposit, TokenMapping, Unsupported}
function getSyncTypeAndData(bytes memory data) internal pure returns(bytes32, bytes memory) {
(bytes32 syncType, bytes memory syncData) = abi.decode(data, (bytes32, bytes));
return (syncType, syncData);
function decodeStateSyncData(bytes calldata data) external pure returns (SyncType, address, address, bytes memory){
(bytes32 syncType, bytes memory syncData) = getSyncTypeAndData(data);
if (syncType == MAP_TOKEN) {
(address root, address child, ) = abi.decode(syncData, (address, address, bytes32));
return (SyncType.TokenMapping, root, child, "");
if (syncType == DEPOSIT) {
(address depositor, address root, bytes memory depositData) = abi.decode(syncData, (address, address, bytes));
return (SyncType.Deposit, depositor, root, depositData);
return (SyncType.Unsupported, address(0), address(0), "");
function decodeERC20Deposit(bytes calldata depositData) external pure returns(uint256) {
return abi.decode(depositData, (uint256));
function decodeERC721SingleDeposit(bytes calldata depositData) external pure returns(uint256) {
return abi.decode(depositData, (uint256));
function decodeERC721BatchDeposit(bytes calldata depositData) external pure returns(uint256[] memory) {
return abi.decode(depositData, (uint256[]));
function decodeERC1155BatchDeposit(bytes calldata depositData) external pure returns(uint256[] memory, uint256[] memory, bytes memory) {
return abi.decode(depositData, (uint256[], uint256[], bytes));
Copy link


👆 contract is written for using it in combination with Matic Network's The Graph deployment, so that, caught StateSync event's data field can be decoded & put in The Graph.

It's capable of decoding both general Deposit & TokenMapping state syncs.


  • If you've StateSync data, you can call decodeStateSyncData to unwrap first two folds.

  • In response, if your first field ∈ {0, 1}, we've successfully decoded data

    • 0 -> Deposit
      • depositor => Address performing deposit on Ethereum
      • root => Token which is being deposited
      • depositData => ABI encoded deposit data i.e. might contain token amount ( for Ether, ERC20 ), token id(s) ( for ERC721 ), token id(s) & amount ( for ERC1155 )
    • 1 -> Token Mapping
      • root => Root chain token address of token mapping
      • child => Child chain token address of token mapping
  • For decoding depositData, obtained from 👆, respective decoder function can be used depending upon what kind of token, you're dealing with.

Deployment Details

Source verified version of Decoder is deployed on

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment