Across

Across is a bridge protocol, so the parser focuses on identifying BRIDGE_OUT and BRIDGE_IN actions from its on-chain events.


🧩 Files Involved in the Across Parser

src/lib/Across/
├── abis/SpokePool.json   ← Only needed ABI fragments
├── contracts.ts          ← Address + event signature map
├── parser.ts             ← Logic to build actions from tx logs
└── index.ts              ← Parser class exposed to the framework

1. contracts.ts — Contract Definitions & Event Signatures

This file defines which contracts Across uses on each chain, and how to identify the logs they emit.

export enum ACROSS_CONTRACTS {
  SPOKE_POOL = "SPOKE_POOL"
}

export const acrossContracts: IProtocolContractDefinitions = {
  [CHAIN_ID.ETHEREUM]: {
    [ACROSS_CONTRACTS.SPOKE_POOL]: {
      address: "0x...",  // SpokePool address on Ethereum
      listener: LISTEN_FOR_TRANSACTIONS.TO,
      abi: SpokePoolABI,
      events: {
        FilledRelay: "FilledRelay(address,address,address,uint256,uint256,uint256,bool,bytes32)",
        Deposited: "Deposited(address,address,address,uint256,uint256,uint256,bytes32)"
      }
    }
  },
  ...
};

Here we:

  • Define what contract to listen to (e.g. SpokePool)

  • Where to listen (to or from in tx)

  • Which events (logs) we care about


2. parser.ts — Parsing the Logs into Actions

export const parseAcrossTx = (tx: ITransaction, helper: ProtocolHelper): ITransactionAction[] => {
  const actions: ITransactionAction[] = [];

  for (const log of tx.logs) {
    const parsed = helper.parseLog(log);
    if (!parsed) continue;

    const { name, args } = parsed;

    if (name === "FilledRelay") {
      actions.push({
        action: ACTION_ENUM.BRIDGE_IN,
        chainId: tx.chainId,
        from: args.originToken,
        to: args.destinationToken,
        amount: args.amount,
        userAddress: args.recipient,
        txHash: tx.hash,
        timestamp: tx.timestamp
      });
    }

    if (name === "Deposited") {
      actions.push({
        action: ACTION_ENUM.BRIDGE_OUT,
        chainId: tx.chainId,
        from: args.originToken,
        to: args.destinationToken,
        amount: args.amount,
        userAddress: args.depositor,
        txHash: tx.hash,
        timestamp: tx.timestamp
      });
    }
  }

  return actions;
};

🧠 Note:

  • It loops through logs, uses a helper to parse each log via ABI

  • Builds high-level ITransactionAction objects

  • Each action gets: action, chainId, tokens, user, amount, timestamp


3. index.ts — The Parser Class

export default class Across implements IProtocolParserExport {
  readonly protocolIdentifier = "across";

  parseTransaction(tx: ITransaction): ITransactionAction[] {
    const helper = new ProtocolHelper(acrossContracts, tx);
    if (!helper.txToAnyContract()) return [];

    return parseAcrossTx(tx, helper);
  }

  getProtocolContracts() {
    return acrossContracts;
  }
}

This is the entry point used by the global parser map. It:

  1. Uses ProtocolHelper to check if the tx is related to Across

  2. If yes, passes it to parseAcrossTx

  3. Returns any ITransactionActions it detects


Recap: How Across Parser Works

Stage
What Happens

Contract Setup

Define SpokePool addresses and events in contracts.ts

Parsing Logic

Loop through logs and map to BRIDGE_IN / BRIDGE_OUT

Runtime Class

Implements IProtocolParserExport to plug into SDK

Output

Returns typed ITransactionAction[] used for OpenRep scoring

Last updated