# @uma/fx-tunnel-relayer

> Relayer bot to support UMA's Polygon-Ethereum oracle bridge

Latest version **1.4.2** (published 2025-09-24) · AGPL-3.0-or-later license · 0 weekly downloads

## Install

```sh
npm install @uma/fx-tunnel-relayer
pnpm add @uma/fx-tunnel-relayer
yarn add @uma/fx-tunnel-relayer
bun add @uma/fx-tunnel-relayer
```

Provides the command `fx-tunnel-relayer`.

## Health

**Score 50/100 (C)** — status: stable.

Positive: has types; no vulnerabilities; high maintenance score; high quality score.

Warnings: low downloads; no esm support.

Negative: stale.

## Facts

| | |
|---|---|
| Version | 1.4.2 |
| Published | 2025-09-24 |
| First published | 2021-08-18 |
| Weekly downloads | 0 |
| License | AGPL-3.0-or-later |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 7 |
| Unpacked size | 72.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 486 |
| Maintainers | mrice32, chrismaree, evaldofelipe, nicholaspai |

## Links

- npm: https://www.npmjs.com/package/@uma/fx-tunnel-relayer
- Repository: https://github.com/UMAprotocol/protocol
- Homepage: https://umaproject.org
- Issues: https://github.com/UMAprotocol/protocol/issues
- npm.io page: https://npm.io/package/@uma/fx-tunnel-relayer

## Dependencies (7)

- [dotenv](https://npm.io/package/dotenv.md) ^8.2.0
- [@uma/common](https://npm.io/package/@uma/common.md) ^2.40.0
- [async-retry](https://npm.io/package/async-retry.md) ^1.3.1
- [@uma/contracts-node](https://npm.io/package/@uma/contracts-node.md) ^0.4.28
- [@maticnetwork/maticjs](https://npm.io/package/@maticnetwork/maticjs.md) ^3.6.6
- [@maticnetwork/maticjs-web3](https://npm.io/package/@maticnetwork/maticjs-web3.md) ^1.0.4
- [@uma/financial-templates-lib](https://npm.io/package/@uma/financial-templates-lib.md) ^2.37.2

## Recent versions

- 1.4.2 (latest) — 2025-09-24
- 1.4.0 — 2025-07-15
- 1.3.45 — 2024-10-29
- 1.3.43 — 2024-07-20
- 1.3.42 — 2024-04-30
- 1.3.41 — 2024-04-09
- 1.3.40 — 2024-03-07
- 1.3.39 — 2023-11-13
- 1.3.38 — 2023-10-13
- 1.3.37 — 2023-09-28
- 1.3.36 — 2023-07-17
- 1.3.35 — 2023-04-18
- 1.3.34 — 2023-03-30
- 1.3.33 — 2023-03-23
- 1.3.32 — 2023-03-16
- … 54 more at https://npm.io/package/@uma/fx-tunnel-relayer/versions

## README

# Fx Tunnel Relayer

This bot is specific to the Polygon-Ethereum communication layer whose architecture can be found [here](https://github.com/UMAprotocol/protocol/blob/2c3d172d4f3787ef6914788e2c0c8c7d3b1ff7fd/packages/core/contracts/polygon/README.md). In summary, the bot listens for events from the Polygon Oracle contract, emitted when a cross-chain price request is submitted, and then relays the price request to the Ethereum Oracle (i.e. the DVM) after the Polygon block containing the event is [checkpointed](https://docs.matic.network/docs/validate/basics/checkpoint-mechanism/) to Ethereum.

# Run

- `yarn build` to compile code.
- Set environment variables including required `CUSTOM_NODE_URL` and `POLYGON_CUSTOM_NODE_URL` values which correspond to Ethereum and Polygon nodes respectively.
- Optionally set SKIP_THRESHOLD_SECONDS (seconds to skip relay when close to end of phase; default 14400 = 4 hours).
- `node ./dist/src/index.js --network mainnet_mnemonic` or `ts-node ./src/index.js --network mainnet_mnemonic`.

# Why is a bot needed to relay messages from Polygon to Ethereum?

Polygon-Ethereum communication differs based on the direction that a message is sent. If a message is sent from Ethereum to Polygon, then the Polygon [State Sync](https://docs.polygon.technology/docs/contribute/state-sync/state-sync/) mechanism takes over. This relies on Polygon validators to detect `StateSynced` events emitted by the Ethereum [StateSender](https://docs.polygon.technology/docs/contribute/state-sync/how-state-sync-works) contract. Validators are incentivized to pick up these events and submit corresponding metadata to a receiver contract on the Polygon network. The metadata includes a target contract and ABI data that the receiver contract can use to forward a smart contract call. Therefore the Ethereum-to-Polygon messaging is handled automatically by Polygon validators.

However, Polygon-to-Ethereum communication requires manual intervention. While validators _continuously_ monitor the `StateSender` contract on Ethereum to relay data from Ethereum to Polygon, they _periodically_ submit a merkle tree containing transaction hashes that facilitate relaying data from Polygon to Ethereum. Once a merkle tree containing a Polygon transaction is submitted to Ethereum, the transaction is said to be "verified" to have happened on Polygon, and corresponding action can be taken on Ethereum.

Once a Polygon transaction is included in a merkle root submitted to Ethereum, the following manual action must be taken to finalize the Polygon-to-Ethereum communication:

- Construct a proof that the transaction has been included in a checkpoint. Example code below, source [here](https://docs.polygon.technology/docs/develop/l1-l2-communication/state-transfer#state-transfer-from-polygon-to-ethereum).

```js
// source code: https://maticnetwork.github.io/matic.js/docs/advanced/exit-util/
// npm i @maticnetwork/maticjs @maticnetwork/maticjs-web3
import MaticJs from "@maticnetwork/maticjs";
import MaticJsWeb3 from "@maticnetwork/maticjs-web3";

MaticJs.use(MaticJsWeb3.Web3ClientPlugin);

const posClient = new MaticJs.POSClient();
await posClient.init({
    network: 'mainnet', // "testnet"
    version: 'v1', // "mumbai"
    parent: {
      provider: mainnetWeb3.provider,
      defaultConfig: {
        from : fromAddress
      }
    },
    child: {
      provider: polygonWeb3.provider,
      defaultConfig: {
        from : fromAddress
      }
    }
});

const proof = await posClient.exitUtil.buildPayloadForExit(
    "0x3cc9f7e675bb4f6af87ee99947bf24c38cbffa0b933d8c981644a2f2b550e66a", // replace with txn hash,
    "0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036" // SEND_MESSAGE_EVENT_SIG do not change,
    false // isFast; unclear what this variable does but setting to true requires a "proof API" so I set to False and it works.
)
```

- Call a RootTunnel contract on Ethereum and include the proof as a function parameter to the `receiveMessage(bytes)` function. [Here's](https://etherscan.io/tx/0x45dbe26471107ac1554d0f8c030e2ce58ec458be05b7df6987051f0c423b09c5) an example execution of `receiveMessage` that succesfully bridged a Polygon price request to an Oracle contract on Ethereum. (Note that the Oracle for this example was a `MockOracle`, not the DVM). [This](https://polygonscan.com/tx/0x6a9eca71268c74668bd69f0db250308c771f0983984c86726cc848c441605b86) was the preceding Polygon price request that needed to be included in the checkpoint beforehand.

# Bot algorithm

- Detect `MessageSent` events emitted by the `OracleChildTunnel` on Polygon whenever a cross-chain price request is submitted to it, usually by the `OptimisticOracle` but can be sent by any registered contract.
- Attempt to construct a proof for the transaction hashes containing the `MessageSent` events. This step will fail and exit silently if the hash has not been checkpointed to Ethereum yet.
- Include the proof in a `receiveMessage` function call to the `OracleRootTunnel`. This step will fail and exit silently if the proof has already been included in a call.

---
_Source: https://npm.io/package/@uma/fx-tunnel-relayer · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
