npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ruban-labs/web3-tx-parser

v0.24.0

Published

Extensible TypeScript transaction intent parser for EVM calldata.

Readme

web3-tx-parser

An extensible TypeScript parser for EVM transaction intent. It is inspired by the layered design used by wallet backends: normalize a transaction, decode calldata through an ABI registry, select the most specific parser route, and fall back safely to a human-readable contract call.

It intentionally does not execute remotely stored code or query an RPC endpoint by itself. Callers provide contract identity metadata when they have it, which keeps the package deterministic and suitable for wallets, indexers, and simulation pipelines.

Included parsers

  • native transfers, contract deployment, and nonce-cancel transactions;
  • ERC-20 transfer, transferFrom, approve, increaseAllowance, decreaseAllowance, and EIP-2612-style permit when the caller supplies trusted ERC-20 context;
  • ERC-721 transferFrom, safeTransferFrom, and token-level approval/revoke when the caller supplies trusted contract-standard context;
  • ERC-1155 safeTransferFrom and safeBatchTransferFrom when the caller supplies trusted contract-standard context;
  • ERC-721/1155-style setApprovalForAll when the caller supplies trusted NFT context;
  • direct WETH-compatible deposit() and withdraw(uint256) calls, only for explicitly configured wrapped-native deployments;
  • direct wstETH-style wrap(uint256) and unwrap(uint256) calls, only for explicitly configured wrapper and underlying-token pairs;
  • ERC-4626 deposit, mint, withdraw, and redeem, only for explicitly configured vault and underlying-asset pairs;
  • Permit2 direct allowance approve, signed single/batch allowance permit, one-time signature transfer, and lockdown, only for explicitly configured Permit2 deployments;
  • Safe execTransaction outer-call summaries, only for explicitly configured Safe smart-account deployments;
  • Aave V3 Pool supply/borrow/repay requests (including permit and aToken variants) plus explicit collateral-use, eMode-category, and borrow-rate-mode changes, only for explicitly configured Pool deployments;
  • Balancer V2 Vault direct, single-pool swap requests, only for explicitly configured Vault deployments and the unambiguous empty-userData, external-balance settlement form;
  • Lido stETH submit(address) staking requests, only for explicitly configured staking-pool deployments;
  • Lido WithdrawalQueue stETH/wstETH requests and withdrawal claims, only for explicitly configured queue and token bindings;
  • EigenLayer StrategyManager depositIntoStrategy and depositIntoStrategyWithSignature, only for explicitly configured StrategyManager deployments;
  • Compound V2 cToken supply, redeem, borrow, and repay requests, only for explicitly configured cTokens and caller-supplied ERC-20/native underlying forms;
  • Curve index-based exchange and exchange_underlying requests, only for explicitly configured pools and caller-supplied coin-order bindings;
  • Across V3 SpokePool direct depositV3 bridge requests, only for explicitly configured SpokePools; native-input form additionally requires an explicit wrapped-native token and an empty destination message;
  • Connext direct xcall bridge requests, only for explicitly configured deployments and explicit Connext-domain-to-EVM-chain bindings; calls with destination calldata remain generic contract calls;
  • Wormhole Token Bridge direct ERC-20 transferTokens requests, only for explicitly configured deployments and Wormhole-chain-id-to-EVM-chain bindings; payload and wrapped-native calls remain generic contract calls;
  • Wormhole Native Token Transfers (NTT) Manager direct basic/advanced transfer requests, only for explicitly configured Managers, source assets, and Wormhole-chain-id-to-EVM-chain bindings; transceiver instructions stay opaque and queue/delivery state is never inferred;
  • Hyperlane Warp Route direct transferRemote requests, only for explicitly configured TokenRouters, source assets, and Hyperlane-domain-to-EVM-chain bindings;
  • Axelar Interchain Token Service direct token-only interchainTransfer requests, only for explicitly configured ITS deployments, token-id-to-asset, and Axelar-chain-name-to-EVM-chain bindings; metadata-bearing calls remain generic contract calls;
  • Arbitrum L1 Inbox direct native depositEth() requests, only for explicitly configured Inbox deployments and destination chain ids;
  • Arbitrum L1 Gateway Router direct ERC-20 outboundTransfer deposits, only for explicitly configured routers and destination chains with canonical, empty-call-hook retryable-ticket data;
  • Arbitrum L2 ArbSys direct native withdrawEth(address) requests, only for explicitly configured precompile source/destination chains; L2-to-L1 message inclusion, proof, and L1 execution remain unresolved;
  • Arbitrum L2 Gateway Router direct ERC-20 outboundTransfer requests, only for explicitly configured routers and destination chains with zero outer value and empty extra data;
  • Hashflow legacy Router direct same-chain RFQ-t tradeSingleHop requests, only for explicitly configured Router deployments and complete signed quote calldata;
  • OrbiterRouterV3 direct native transfer and ERC-20 transferToken Maker bridge requests, only for explicitly configured Router deployments; the amount suffix and extension remain opaque, so destination chain, asset, and final recipient are never guessed;
  • Celer cBridge V2 direct native sendNative and ERC-20 send liquidity-pool bridge requests, only for explicitly configured Bridge deployments and explicit cBridge-id-to-EVM-chain bindings; destination token, fee, and delivered amount remain unresolved;
  • Circle CCTP V1 direct depositForBurn requests, only for explicitly configured TokenMessenger deployments and explicit CCTP-domain-to-EVM-chain bindings; non-EVM bytes32 recipients remain opaque;
  • Circle CCTP V2 direct no-hook depositForBurn requests, only for explicitly configured V2 TokenMessenger deployments and explicit CCTP-domain-to-EVM-chain bindings; maximum fee, finality threshold, and destination caller remain explicit while hook-bearing burns stay generic calls;
  • LayerZero V2 OFT direct, non-composed send requests, only for explicitly configured OFT deployments and explicit endpoint-id-to-EVM-chain bindings; destination compose messages and OFT commands stay generic calls;
  • Polygon PoS RootChainManager direct ETH/ERC-20 deposit requests, only for explicitly configured manager deployments and destination chain ids;
  • Fraxswap Multihop Router direct no-permit swaps, only for explicitly configured Router deployments and complete non-empty route calldata;
  • Rubicon Router direct token/native swaps, only for explicitly configured Router deployments and their caller-supplied wrapped-native token;
  • Yield Yak Router direct exact-input swaps, only for explicitly configured Router deployments and structurally complete path/adapter calldata;
  • Ambient/CrocSwap direct hot-path swaps, only for explicitly configured Dex deployments and an opt-in native virtual-token address where applicable;
  • Polygon zkEVM Bridge direct native bridgeAsset requests, only for explicitly configured bridge deployments and bridge-network-to-EVM-chain bindings;
  • WOO Network Router direct exact-input swaps, only for explicitly configured Router deployments and an optional, caller-supplied native-token sentinel;
  • Stargate V1 RouterETH swapETH bridge requests, only for explicitly configured native routers and explicit Stargate-id-to-EVM-chain bindings;
  • Stargate V1 Router ERC-20 swap bridge requests, only for explicitly configured pool-to-token and Stargate-id-to-EVM-chain bindings, with no destination callback, destination gas, or native-token drop;
  • OP Stack Standard Bridge direct ETH/ERC-20 deposits and legacy L2 ERC-20 withdrawal requests, only for explicitly configured bridge deployments and destination chain ids; withdrawal destination-token mappings stay unresolved, and native legacy withdrawals additionally require an explicit placeholder;
  • OP Stack Portal direct plain-ETH depositTransaction requests, only for explicitly configured portals, destination chains, and empty L2 calldata;
  • zkSync BridgeHub direct plain native self-deposits, only for explicitly configured BridgeHubs and destination-id-to-EVM-chain bindings; arbitrary L2 calls, third-party recipients/refunds, factory dependencies, and ERC-20 base assets stay generic calls;
  • Scroll L1 Gateway Router direct ETH deposits, only for explicitly configured routers and destination chains; L2 callback and ERC-20 forms remain generic because they require additional execution or token-mapping context;
  • Hop L1 sendToL2 bridge requests, only for explicitly configured bridge source assets and Hop-id-to-EVM-chain bindings;
  • Trader Joe Liquidity Book direct exact-input/exact-output routes, only for explicitly configured routers and caller-supplied wrapped-native tokens where needed;
  • Wombat direct exact-input routes, only for explicitly configured Routers and caller-supplied wrapped-native tokens where needed;
  • Velodrome V1/V2 Router direct exact-input swaps, only for explicitly configured Routers and caller-supplied wrapped-native tokens where needed;
  • Compound V3 Comet supply*, withdraw*, and direct account-manager authorization requests, only for explicitly configured Comet deployments;
  • ERC-3009 transferWithAuthorization, receiveWithAuthorization, and cancelAuthorization, only for explicitly configured token deployments;
  • Uniswap V2-compatible Router's six standard exact-input/exact-output simple swap methods, only for explicitly configured routers; native paths also require a caller-supplied wrapped-native token;
  • optional Uniswap V3 exactInput* and exactOutput* router parsing;
  • optional Uniswap Universal Router V2/V3 direct-swap parsing and narrowly validated exact-input native-input/native-output settlement pairs;
  • generic ABI-decoded contract_call fallback.

Quick start

import {
  createDefaultParser,
  parseAbi,
  type TransactionInput,
} from '@ruban-labs/web3-tx-parser';

const parser = createDefaultParser({
  acrossV3SpokePools: [{
    chainId: 1,
    address: '0x5c7BCd6E7De5423a257D81B442095A1a6ced35C5',
    // Required only to label payable WETH input as native ETH.
    wrappedNativeToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
  }],
  connexts: [{
    chainId: 10,
    address: '0x8f7492DE823025b4CfaAB1D34c58963F2af5DEDA',
    // Connext domains are a separate uint32 namespace, not EVM chain ids.
    destinations: [{ domain: 6648936, chainId: 1 }],
  }],
  wormholeTokenBridges: [{
    chainId: 1,
    address: '0x3ee18B2214AFF97000D974cf647E7C347E8fa585',
    // Wormhole uint16 chain ids are a distinct namespace, not EVM chain ids.
    destinations: [{ wormholeChainId: 4, chainId: 56 }],
  }],
  wormholeNativeTokenTransferManagers: [{
    chainId: 1,
    address: '0x5293158bf7a81ed05418da497a80f7e6dbf4477e',
    // Required: never read the NTT Manager's token() state from the network.
    asset: '0xdd468a1ddc392dcdbef6db6e34e89aa338f9f186',
    destinations: [{ wormholeChainId: 30, chainId: 8453 }],
  }],
  hyperlaneTokenRouters: [{
    chainId: 1,
    address: '0x44f161ae29361e332dea039dfa2f404e0bc5b5cc',
    // Required: Router calldata does not identify the source asset.
    asset: '0xcf5104d094e3864cfcbda43b82e1cefd26a016eb',
    // Hyperlane domains are separate uint32 identifiers, even when equal here.
    destinations: [{ domain: 56, chainId: 56 }],
  }],
  axelarInterchainTokenServices: [{
    chainId: 1,
    address: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C',
    // ITS chain names and token ids are protocol-specific, not network lookups.
    destinations: [{ destinationChain: 'binance', chainId: 56 }],
    tokens: [{
      tokenId: '0x4eed4be1acf5e047f86fed1d359d4767bb2569b42c9aac71e91d27efc56b8815',
      asset: '0x2598c30330d5771ae9f983979209486ae26de875',
    }],
  }],
  arbitrumL1EthInboxes: [{
    chainId: 1,
    address: '0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f',
    destinationChainId: 42161,
  }],
  arbitrumL1GatewayRouters: [{
    chainId: 1,
    address: '0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef',
    destinationChainId: 42161,
  }],
  arbitrumArbSysPrecompiles: [{
    chainId: 42161,
    address: '0x0000000000000000000000000000000000000064',
    // The precompile address is shared by Arbitrum deployments, so the
    // destination chain must still be supplied by trusted application config.
    destinationChainId: 1,
  }],
  arbitrumL2GatewayRouters: [{
    chainId: 42161,
    address: '0x5288c571Fd7aD117beA99bF60FE0846C4E84F933',
    destinationChainId: 1,
  }],
  hashflowRouters: [{
    chainId: 1,
    address: '0xF6a94dfD0E6ea9ddFdFfE4762Ad4236576136613',
  }],
  orbiterRouters: [{
    chainId: 42161,
    address: '0x6a065083886ec63d274b8e1fe19ae2ddf498bfdd',
    // Destination chain/recipient must come from separate trusted metadata.
  }],
  celerCbridgeBridges: [{
    chainId: 1,
    address: '0x5427fefa711eff984124bfbb1ab6fbf5e3da1820',
    // cBridge uint64 ids are bound explicitly; they are never assumed to be
    // EVM chain ids just because some deployments currently use matching ids.
    destinations: [{ cbridgeChainId: '42161', chainId: 42161 }],
  }],
  circleCctpV1TokenMessengers: [{
    chainId: 1,
    address: '0xbd3fa81b58ba92a82136038b25adec7066af3155',
    // Circle CCTP domain ids are distinct from EVM chain ids.
    destinations: [{ domain: 3, chainId: 42161 }],
  }],
  circleCctpV2TokenMessengers: [{
    chainId: 1,
    address: '0x28b5a0e9c621a5badaa536219b3a228c8168cf5d',
    // CCTP V2 domains also require explicit bindings.
    destinations: [{ domain: 6, chainId: 8453 }],
  }],
  layerZeroV2Ofts: [{
    chainId: 1,
    address: '0x19cfce47ed54a88614648dc3f19a5980097007dd',
    // LayerZero V2 endpoint ids are distinct from EVM chain ids.
    destinations: [{ endpointId: 30102, chainId: 56 }],
  }],
  stargateV2Pools: [{
    chainId: 1,
    address: '0x77b2043768d28e9c9ab44e1abfc95944bce57931',
    // Required because sendToken calldata does not contain source token identity.
    asset: 'native',
    // Stargate V2 uses LayerZero endpoint ids, not EVM chain ids.
    destinations: [{ endpointId: 30110, chainId: 42161 }],
  }],
  polygonPoSRootChainManagers: [{
    chainId: 1,
    address: '0xA0c68C638235ee32657e8f720a23ceC1bFc77C77',
    destinationChainId: 137,
  }],
  fraxswapRouters: [{
    chainId: 1,
    address: '0x25e9acA5951262241290841b6f863d59D37DC4f0',
  }],
  rubiconRouters: [{
    chainId: 10,
    address: '0x7Af14ADc8Aea70f063c7eA3B2C1AD0D7A59C4bFf',
    // Required to distinguish swapForETH/swapWithETH native endpoints.
    wrappedNativeToken: '0x4200000000000000000000000000000000000006',
  }],
  yieldYakRouters: [{
    chainId: 43114,
    address: '0xC4729E56b831d74bBc18797e0e17A295fA77488c',
  }],
  ambientCrocDexes: [{
    chainId: 1,
    address: '0xAaAaAAAaA24eEeb8d57D431224f73832bC34f688',
    // Opt in only after trusted deployment metadata establishes this sentinel.
    nativeToken: '0x0000000000000000000000000000000000000000',
  }],
  polygonZkEvmBridges: [{
    chainId: 1,
    address: '0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe',
    // Polygon Bridge network ids are not EVM chain ids; bind every one used.
    destinations: [{ networkId: 1, chainId: 1101 }],
  }],
  wooNetworkRouters: [{
    chainId: 42161,
    address: '0x9aEd3A8896A85FE9a8CAc52C9B402D092B629a30',
    // Required only to label this deployment's sentinel as native.
    nativeTokenSentinel: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
  }],
  stargateV1NativeRouters: [{
    chainId: 1,
    address: '0x150f94B44927F078737562f0fcF3C95c01Cc2376',
    // Stargate's uint16 id is not the EVM chain id; bind it explicitly.
    destinations: [{ stargateChainId: 184, chainId: 8453 }],
  }],
  stargateV1TokenRouters: [{
    chainId: 1,
    address: '0x8731d54E9D02c286767d56ac03e8037C07e01e98',
    destinations: [{
      // A Stargate id and pool id do not encode an EVM chain or token.
      stargateChainId: 110,
      chainId: 42161,
      pools: [{
        sourcePoolId: 2,
        destinationPoolId: 1,
        sourceToken: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
        destinationToken: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8',
      }],
    }],
  }],
  opStandardBridges: [{
    chainId: 1,
    address: '0x99c9fc46f92e8a1c0dec1b1747d010903e884be1',
    destinationChainId: 10,
  }],
  opStackPortals: [{
    chainId: 1,
    address: '0xbeb5fc579115071764c7423a4f12edde41f106ed',
    // Portal deployments do not encode a destination EVM chain id.
    destinationChainId: 10,
  }],
  zksyncBridgehubs: [{
    chainId: 1,
    address: '0x303a465b659cbb0ab36ee643ea362c509eeb5213',
    // BridgeHub registration is caller-supplied; do not discover it over RPC.
    destinations: [{ zksyncChainId: '2787', chainId: 2787 }],
  }],
  scrollL1GatewayRouters: [{
    chainId: 1,
    address: '0xF8B1378579659D8F7EE5f3C929c2f3E332E41Fd6',
    destinationChainId: 534352,
  }],
  hopL1Bridges: [{
    chainId: 1,
    address: '0xb8901acb165ed027e32754e0ffe830802919727f',
    asset: { kind: 'native' },
    destinations: [{ hopChainId: 8453, chainId: 8453 }],
  }],
  traderJoeLiquidityBookRouters: [{
    chainId: 56,
    address: '0xb4315e873dbcf96ffd0acd8ea43f689d8c20fb30',
    wrappedNativeToken: '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c',
  }],
  wombatRouters: [{
    chainId: 42161,
    address: '0xc4b2f992496376c6127e73f1211450322e580668',
    wrappedNativeToken: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1',
  }],
  uniswapV2Routers: [
    {
      chainId: 1,
      address: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
      wrappedNativeToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
    },
  ],
  velodromeRouters: [
    {
      chainId: 10,
      address: '0xa062aE8A9c5e11aaA026fc2670B0D65cCc8B2858',
      wrappedNativeToken: '0x4200000000000000000000000000000000000006',
    },
  ],
  uniswapV3Routers: [
    { chainId: 1, address: '0xE592427A0AEce92De3Edee1F18E0157C05861564' },
  ],
  uniswapUniversalRouters: [
    {
      chainId: 1,
      address: '0x66a9893cc07d91d95644aedd05d03f95e1dba8af',
      wrappedNativeToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
    },
  ],
  wrappedNativeTokens: [
    { chainId: 1, address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' },
  ],
  wstEthWrappers: [
    {
      chainId: 1,
      address: '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0',
      underlyingToken: '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84',
    },
  ],
  erc4626Vaults: [
    {
      chainId: 1,
      address: '0x0000000000000000000000000000000000000010',
      asset: '0x0000000000000000000000000000000000000011',
    },
  ],
  permit2Deployments: [
    { chainId: 1, address: '0x0000000000000000000000000000000000000012' },
  ],
  safeDeployments: [
    { chainId: 1, address: '0x0000000000000000000000000000000000000015' },
  ],
  aaveV3Pools: [
    { chainId: 1, address: '0x0000000000000000000000000000000000000017' },
  ],
  balancerV2Vaults: [
    { chainId: 1, address: '0xBA12222222228d8Ba445958a75a0704d566BF2C8' },
  ],
  lidoStakingPools: [
    { chainId: 1, address: '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84' },
  ],
  lidoWithdrawalQueues: [{
    chainId: 1,
    address: '0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1',
    stEthToken: '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84',
    wstEthToken: '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0',
  }],
  eigenLayerStrategyManagers: [
    { chainId: 1, address: '0x858646372CC42E1A627fcE94aa7A7033e7CF075A' },
  ],
  compoundV2CTokens: [{
    chainId: 1,
    address: '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643',
    underlying: { kind: 'erc20', address: '0x6B175474E89094C44Da98b954EedeAC495271d0F' },
  }],
  curvePools: [{
    chainId: 1,
    address: '0xc73B0328Bd40Ea35Aad34d0fDC1dBE64C4f9c59F',
    coins: [
      { kind: 'erc20', address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' },
      { kind: 'erc20', address: '0x294eecec65A0142e84AEdfD8eB2FBEA8c9a9fbad' },
    ],
  }],
  compoundV3Comets: [
    { chainId: 1, address: '0xc3d688B66703497DAA19211EEdff47f25384cdc3' },
  ],
  erc3009Tokens: [
    { chainId: 1, address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' },
  ],
});

const tx: TransactionInput = {
  chainId: 1,
  from: '0x1111111111111111111111111111111111111111',
  to: '0x2222222222222222222222222222222222222222',
  data: '0x',
  value: '0x2386f26fc10000',
};

const result = parser.parse(tx);
// result.action.type === 'native_transfer'

Routing model

Routes are grouped by the four-byte calldata selector. When more than one route matches, the parser uses this deterministic precedence:

  1. exact contract address;
  2. proxy implementation code id;
  3. contract code id;
  4. deployment factory address;
  5. default selector route.

The model keeps parser functions local, typed, and auditable. Register an ABI before a route so the parser can decode the selector into arguments.

const abi = parseAbi(['function deposit(uint256 assets,address receiver)']);

parser.registerAbi({ signature: 'deposit(uint256,address)', abi });
parser.addRoute({
  id: 'vault-deposit',
  selector: '0x6e553f65',
  match: { kind: 'contract', value: '0x1234000000000000000000000000000000005678' },
  handler: ({ decoded }) => ({
    type: 'contract_call',
    data: { kind: 'vault_deposit', function: decoded?.name, args: decoded?.args },
  }),
});

TransactionInput.contract is optional metadata supplied by a caller that has already resolved proxy, bytecode, or factory information. The parser never trusts an RPC response it did not receive.

Token-standard context

Some EVM selectors describe more than one standard, and any selector can be implemented by an unrelated contract. For example, approve(address,uint256) can be either an ERC-20 allowance or an ERC-721 token approval. Calldata alone cannot establish which interpretation is true. When an indexing layer has resolved the contract standard, pass it explicitly:

const result = parser.parse({
  chainId: 1,
  from: '0x1111111111111111111111111111111111111111',
  to: '0x3333333333333333333333333333333333333333',
  data: erc721ApproveCalldata,
  contract: { tokenStandard: 'erc721' },
});

Without trusted tokenStandard, standard-token routes deliberately return the ABI-decoded contract_call fallback instead of guessing. This applies to ERC-20 transfers and allowances as well as NFT transfers and collection approvals.

For allowance actions, data.amount is the exact unsigned integer present in calldata. data.allowanceOperation distinguishes an absolute approve (set) from increaseAllowance (increase), decreaseAllowance (decrease), and EIP-2612-style permit (permit), so a wallet does not mistake a delta for the resulting allowance. A permit's owner and deadline come from calldata; the transaction sender can be a relayer and is not substituted for the owner.

Wrapped-native deployments

deposit() and withdraw(uint256) selectors are not sufficient proof that an arbitrary contract wraps a chain's native currency. Register each trusted deployment explicitly, including its chain id:

const parser = createDefaultParser({
  wrappedNativeTokens: [
    { chainId: 1, address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' },
  ],
});

For a matching deposit(), the parser returns wrap_native with the exact transaction value. For a matching withdraw(uint256), it returns unwrap_native with the exact calldata amount, but only when transaction value is zero. An unconfigured address, a different chain, or a withdrawal carrying native value stays on the conservative ABI/unknown fallback path.

wstETH-style token wrappers

For a configured wstETH-style deployment, wrap(uint256) yields wrap_token and unwrap(uint256) yields unwrap_token. tokenIn, tokenOut, and amountIn are all exact calldata/configuration facts. The wrapper's exchange rate changes with contract state, so no amountOut is predicted; applications may obtain that independently through simulation or their own trusted state layer. Calls carrying native value, unknown wrapper addresses, or unknown underlying tokens remain conservative fallbacks.

ERC-4626 vaults

Register an ERC-4626 vault with its trusted asset address. The parser then returns vault_deposit, vault_mint, vault_withdraw, or vault_redeem for the four standardized write methods. It retains the requested, guaranteed side of the action—assets for deposit/withdraw and shares for mint/redeem—plus the exact calldata receiver and, where present, owner.

The corresponding exchange amount depends on the vault's current state and fees. The parser does not call asset(), preview*(), or any RPC method, and therefore never predicts that counterpart. Calls with native value, unknown vault addresses, or unknown assets remain generic/unknown fallbacks.

Permit2 allowance actions

Register a Permit2 deployment explicitly before parsing its permission and transfer methods. The parser covers direct approve, signed single/batch permit, and lockdown; it also covers the non-witness single/batch permitTransferFrom signature-transfer overloads. Direct transferFrom, witness-bearing signature transfers, and nonce-invalidation calls remain generic fallbacks because they require separate, more complete review models.

Permit2 results include the explicit approvalContract, token, spender, owner, and unscaled amount. expirationInput is the exact calldata uint48 value. When it is 0, Permit2 turns it into the execution block timestamp, which this offline parser deliberately does not predict. A multi-pair lockdown returns token_revoke_batch; a single pair uses the existing token_revoke form. Signed multi-token permits return token_allowance_batch, retaining their one spender, signature deadline, and the exact amount, expiration input, and nonce of every token entry. This is intentionally neutral because one batch can mix new allowances and zero-amount revocations; the parser does not validate the signature, nonce freshness, or current allowance state.

One-time signature transfers return token_signature_transfer or token_signature_transfer_batch, retaining the token owner, submitting signed spender, recipient, requested amount, signed permitted maximum, nonce, and deadline. The route is emitted only when every requested amount is no greater than its signed maximum and batch entries have matching lengths. It does not validate the signature, ordered/unordered nonce state, deadline, token balance, or token-level approval to Permit2.

Safe smart-account executions

Register each trusted Safe account address before parsing execTransaction. The resulting safe_execution preserves the Safe, submitting executor, inner target, exact inner value, raw inner callData, call versus delegatecall, outer transaction value, and all refund/gas parameters. It does not claim that the submitted signatures are valid, that a threshold is met, that a guard will allow execution, or what the inner calldata will do. Those facts require a separate Safe state/simulation layer and remain outside this pure parser.

Aave V3 Pool requests

Register only the Aave V3 Pool addresses your application trusts. The parser returns request facts for supply, supplyWithPermit, withdraw, borrow, repay, repayWithPermit, and repayWithATokens: pool, caller, asset, amount, beneficiary/recipient, referral code, and stable versus variable rate mode. For the permit-backed supply and repay calls, it also preserves the protocol-defined permit owner (the submitting caller), Pool spender, and deadline. It validates only the calldata's structural signature fields; it does not verify the permit signature, nonce, token permit support, or execution success. It does not infer aToken addresses, collateral enablement, health factor, current debt, liquidity, or interest.

repayWithATokens identifies the repayment source as the caller's reserve aToken balance, while leaving the actual aToken address, balance, and final repaid amount to a state/simulation layer.

For setUserUseReserveAsCollateral, the parser produces an explicit lending_collateral_enable or lending_collateral_disable request for the submitting account and underlying asset. It does not claim that the asset is currently supplied, eligible as collateral, enabled/disabled already, or that the resulting health factor permits the change.

For setUserEMode, lending_emode_set preserves the supplied numeric category id, including 0, without guessing a category label, its configured assets, LTV, liquidation threshold, or whether the requested category can be selected.

For swapBorrowRateMode, lending_rate_mode_swap preserves the caller's current calldata mode and the opposite target implied by the Pool implementation. It does not claim an existing debt balance, rate, or that the swap can pass the Pool's state-dependent validation.

For Aave's uint256.max withdraw/repay sentinel, including permit-backed and aToken-backed repayment, amount remains that exact decimal calldata value and useAllBalance or useAllDebt is set. This means “all at execution time,” not a fabricated numeric balance or debt.

Balancer V2 Vault single swaps

Register every Balancer V2 Vault address that the application trusts. The parser summarizes only direct swap calls whose pool-defined userData is exactly 0x, whose source and destination use external balances, and whose SwapKind is the protocol-defined GivenIn or GivenOut. The swap action preserves Vault, caller, pool id, funds sender and recipient, exact direction, the specified decimal amount, limit, and deadline. For exact: 'in', amount is the input; for exact: 'out', it is the requested output. The counterpart amount is pool-state-dependent and is never fabricated.

The zero asset address is retained as the protocol's native-currency sentinel. For the calldata-proven GivenIn native-input form, inputNative: true is emitted only when outer transaction value equals the supplied input amount; native output is marked with outputNative: true. A GivenOut native input uses a pool-calculated amount, so it conservatively remains a generic ABI-decoded contract call rather than guessing a relation to outer value.

batchSwap, joins, exits, non-empty userData, relayer/internal-balance settlement, pool membership, pool specialization, quotes, token metadata, and execution success remain outside this pure parser. They need a trusted simulation or state layer.

Lido stETH requests

Register each trusted Lido stETH pool before parsing submit(address). The result is lido_stake, preserving the exact native transaction amount and calldata referral address. It deliberately does not predict stETH shares: the issuance ratio is contract state, not calldata.

Lido WithdrawalQueue requests and claims

Register each trusted WithdrawalQueue together with explicit stETH and wstETH addresses. requestWithdrawals* becomes lido_withdrawal_request, preserving the submitting account, eventual unstETH NFT owner, submitted asset, each calldata amount, and their exact sum. The two permit variants additionally surface the signed permit's value and deadline, but never claim its signature is valid. A zero owner is represented as the submitting account, matching the trusted queue's documented behavior.

claimWithdrawal, claimWithdrawals, and claimWithdrawalsTo become lido_withdrawal_claim, preserving request IDs, checkpoint hints where provided, and the final recipient. They intentionally do not contain an ETH amount: a request must first be finalized and its amount can depend on queue/oracle state. The parser does not inspect allowances, balances, permits, request ownership, finalization, hints, or claimability; unknown queues, inconsistent claim batches, and calls carrying native value remain conservative fallbacks.

EigenLayer restaking requests

Register each trusted EigenLayer StrategyManager before parsing depositIntoStrategy(address,address,uint256) or depositIntoStrategyWithSignature(address,address,uint256,address,uint256,bytes). The result is restake_deposit, preserving the manager, selected strategy, token, and exact requested token amount. The signed form separately preserves the funding depositor, credited staker, and signature expiry; it does not claim that its ECDSA/EIP-1271 signature is valid or current.

Neither form infers whether a strategy is whitelisted, whether an allowance is sufficient, execution success, or issued deposit shares: those depend on current chain state and are outside this zero-IO parser.

Compound V2 cToken requests

Register each cToken with an explicit underlying form. Use { kind: 'erc20', address } for CErc20-style markets and { kind: 'native' } for CEther-style markets; the parser never calls underlying() or guesses the market implementation. For an ERC-20 market it summarizes mint(uint256), redeem(uint256), redeemUnderlying(uint256), borrow(uint256), repayBorrow(uint256), and repayBorrowBehalf(address,uint256). For a native market it summarizes payable mint(), zero-calldata receive mints, redeem*, borrow, repayBorrow(), and repayBorrowBehalf(address).

The compound_v2_supply, compound_v2_withdraw, compound_v2_borrow, and compound_v2_repay actions preserve the requested underlying amount. A compound_v2_redeem preserves the exact cToken amount but intentionally does not invent an underlying output: the exchange rate is execution-time state. A native underlying is represented as asset: 'native'; ERC-20 assets retain their configured address. uint256.max in ERC-20 repay calls is preserved and marked useAllDebt: true, reflecting Compound's debt-at-execution sentinel.

No cToken amount minted/redeemed, accrued interest, outstanding debt, collateral eligibility, liquidity, Comptroller result code, or execution success is inferred. Zero or mismatched native values, unconfigured markets, and unsupported cToken methods retain the generic fallback.

Curve index-based swaps

Register each trusted Curve pool together with its exact coins ordering and, when exchange_underlying is intended, its exact underlyingCoins ordering. Every asset is explicit: { kind: 'erc20', address } or { kind: 'native' }. The parser does not call coins() or underlying_coins(), so an out-of-range index or a missing underlying list safely falls back instead of guessing an asset.

The specialized routes cover four-argument and explicit-receiver exchange/exchange_underlying ABIs with signed or unsigned index types. They emit a swap with the pool, caller, recipient, configured asset set, both indexes, exact input amount, and the exact minimum-output limit. A native configured input is accepted only when outer transaction value equals the calldata input; native input/output is marked explicitly.

Five-argument Curve variants carrying protocol-specific flags (such as use_eth), add/remove-liquidity calls, pool-defined receivers or callbacks outside these exact ABI shapes, quotes, fees, output amount, and execution success intentionally remain ABI-decoded generic calls. Those facts require the precise pool implementation and current state.

Celer cBridge V2 liquidity-pool transfers

Register each trusted cBridge V2 Bridge deployment and every permitted uint64 cBridge-destination-id to EVM-chain-id binding. The parser does not assume that a cBridge id is an EVM chain id even when a current route happens to use the same number; absent or duplicate bindings are rejected at registration time, and a call to an unbound destination stays generic.

The direct ERC-20 send and native sendNative entrypoints produce a bridge_transfer request containing sender, recipient, source asset, exact submitted amount, raw cBridge destination id, configured destination EVM chain, nonce, submitted maximum slippage, and attached value. Native parsing requires outer value to equal calldata amount; ERC-20 parsing requires zero outer value.

Destination token identity, bridge liquidity, calculated fee, delivered amount, minimum supported slippage, relay/finality, and recipient delivery are all execution- or state-dependent. They are deliberately not claimed by this pure parser. Message-bus, mint/withdraw, relay, refund, and unsupported Bridge entrypoints remain ABI-decoded generic calls.

Circle CCTP V1 standard burns

Register each trusted CCTP V1 TokenMessenger and every permitted uint32 Circle-domain-to-EVM-chain binding. A Circle domain is not an EVM chain id; an unbound domain stays a generic contract call. The parser supports only the direct four-argument depositForBurn standard-burn ABI, with zero outer value, a non-zero source burn token, a non-zero amount, and a non-zero mintRecipient.

The resulting bridge_transfer preserves the configured destination chain, source burn token, exact burned amount, raw domain, and raw mintRecipient. It additionally exposes recipient only when the bytes32 is a canonical zero-left-padded, non-zero EVM address; all other accepted bytes32 values are marked recipientEncoding: 'opaque-bytes32'. This lets consumers render non-EVM destinations without pretending their byte encoding is an EVM address.

Destination token identity, Circle attestations, finality, fees, relay state, and delivery remain state-dependent and are deliberately outside this pure parser. V1 depositForBurnWithCaller, replacement, message receive, and V2 fee/hook entrypoints remain ABI-decoded generic calls.

Circle CCTP V2 standard burns

Register each trusted CCTP V2 TokenMessenger separately from V1, along with every allowed CCTP-domain-to-EVM-chain binding. The specialized route accepts only the direct seven-argument, no-hook depositForBurn with zero outer ETH, a positive burn amount, non-zero burn token and mint recipient, a valid bound domain, and maxFee < amount.

The result preserves the raw mint-recipient and destination-caller bytes32 values, safely exposing EVM addresses only for canonical zero-left-padded encodings. A zero destination caller is rendered as any-caller; otherwise it is preserved as either an EVM address or opaque bytes32. The caller-supplied maxFee and minFinalityThreshold are retained exactly. They are not an attestation, a quoted final fee, or a guarantee of delivery.

depositForBurnWithHook is registered for ABI visibility but deliberately falls back to contract_call: its hook may drive arbitrary destination-side logic. Attestations, accepted finality, final paid fee, destination token metadata, message receive, mint, and delivery all remain outside this pure, network-free parser.

LayerZero V2 OFT direct sends

Register each trusted LayerZero V2 OFT deployment and every permitted uint32 endpoint-id-to-EVM-chain binding. Endpoint ids are not EVM chain ids, so an unbound endpoint stays a generic contract call. The specialized route accepts only the direct send ABI with a non-zero amountLD, bounded minAmountLD, valid non-zero refund address, and enough attached native value to cover the calldata nativeFee.

For wallet review, the parser supports only plain asset sends: composeMsg and oftCmd must both be empty. Those fields may produce destination-side protocol logic, so non-empty variants intentionally retain the normal ABI-decoded contract-call fallback rather than being mislabeled as a simple transfer. extraOptions is preserved as opaque bytes and an explicit byte length.

The result preserves local-decimal amountLD/minAmountLD, raw endpoint id, raw recipientBytes32, refund address, quoted native/LayerZero-token fees, and attached value. recipient is emitted only for canonical zero-left-padded EVM-address bytes32; other encodings remain opaque-bytes32.

Actual debit/credit amounts, token conversion dust, fee payment in a LayerZero token, endpoint execution, destination delivery, retries, and refunds depend on contract state and execution. They are deliberately not inferred by this pure parser.

Stargate V2 Taxi requests

Register each trusted Stargate V2 pool with its exact source-chain asset and every permitted LayerZero uint32 endpoint-id-to-EVM-chain binding. Pool calldata contains neither a source token address nor an EVM chain id, so both are caller-supplied metadata and must never be guessed or looked up by this package. Set asset: 'native' only for a verified native-token pool; otherwise provide the verified source ERC-20 address.

The specialized route accepts only sendToken Taxi calls: a non-zero amountLD, valid minAmountLD, non-zero refund address, empty composeMsg, and empty oftCmd. For a native pool, outer value must cover at least amountLD + nativeFee; for an ERC-20 pool it must cover at least nativeFee. The result preserves the submitted local-decimal amount/minimum, source asset, configured EVM destination, endpoint id, raw recipient bytes32, refund address, quoted native/LayerZero-token fees, opaque extraOptions, and attached value.

Bus participation and drive-bus commands use non-empty oftCmd; their batching/passenger semantics are intentionally not reduced to a plain bridge transfer. Destination composed messages likewise stay ABI-decoded generic contract calls. The parser also makes no claim about pool liquidity, final fee, destination token contract, amount delivered, bus departure, endpoint execution, or refunds.

Stargate V1 bridge requests

Register a trusted Stargate V1 RouterETH deployment with every permitted destination mapping. A Stargate uint16 destination id is not an EVM chain id, so the parser rejects any unconfigured mapping rather than importing a global chain table or guessing.

Only the direct five-argument swapETH ABI is specialized. It produces a bridge_transfer request with native asset, exact source amount, exact destination minAmount, source/destination ids, packed-address recipient, refund address, and complete outer attachedValue. The RouterETH contract requires attached value above the bridged amount; the excess funds its LayerZero message-fee/refund process, which this parser deliberately does not price or present as a final fee.

ERC-20 Router swap requests are separately supported when the application provides the exact Router, destination Stargate-id-to-EVM-chain binding, and each (destination id, source pool id, destination pool id) token mapping. The resulting bridge_transfer preserves source/destination token addresses, pool ids, submitted amount, submitted minAmount, recipient, refund address, and outer attachedValue. It accepts only an empty payload with zero dstGasForCall and zero dstNativeAmount; these rules exclude destination callbacks and native-token drops. An unused dstNativeAddr byte field may be present when the amount is zero and is not interpreted.

Both forms are bridge requests, never claims that a message was delivered or that the recipient received funds. Callback-capable swapETHAndCall forms, payload-bearing ERC-20 swaps, and any unknown Router/Pool binding remain generic calls. The parser makes no RPC calls to discover Router, Pool, LayerZero, token, fee, or delivery state.

Across V3 bridge deposits

Register each trusted Across V3 SpokePool explicitly. The direct depositV3 calldata supplies the depositor, recipient, input token, optional explicit destination token, input/output amounts, EVM destination chain id, exclusive relayer, and fill timing. The parser emits a submitted bridge_transfer request, not a guarantee of a relayer fill or destination settlement.

Only an empty destination message is specialized. Any non-empty message can invoke destination-side logic and therefore remains an ABI-decoded generic call. An ERC-20 input requires zero outer native value. A payable/native input is recognized only where the consumer supplied the source chain's wrappedNativeToken, the calldata inputToken matches it, and outer value equals the calldata inputAmount; this prevents guessing whether a payable call is an ETH bridge request. When outputToken is zero, Across defines it as the equivalent destination token, so the result carries destinationAssetMode: 'equivalent' rather than inventing an address.

The parser preserves the requested inputAmount and outputAmount as lossless decimal strings plus attachedValue; it does not calculate fees, select a relayer, look up a token representation, or make any network request.

Connext xcall bridge requests

Register each trusted Connext deployment with an explicit mapping from its uint32 domain to an EVM chain id. A domain is its own namespace: the parser does not assume that it equals a chain id or discover a mapping over the network. It recognizes direct xcall only when the destination mapping is configured, the asset and recipient are non-zero, the requested amount is positive, and destination callData is empty.

The emitted bridge_transfer is a request on the origin chain, not an assertion of adopted-asset conversion, relayer fill, destination execution, or recipient delivery. It retains slippage, requestedRelayerFee, and outer attachedValue as lossless decimal strings without calculating or asserting a relationship between them. Non-empty destination calldata, missing bindings, or unconfigured contracts remain ABI-decoded generic calls.

Wormhole Token Bridge ERC-20 requests

Register each trusted Wormhole Wrapped Token Transfers Token Bridge deployment with explicit uint16 Wormhole-chain-id-to-EVM-chain bindings. Wormhole chain ids are not EVM chain ids, so an unbound destination remains an ABI-decoded generic contract call. The specialized route accepts only direct ERC-20 transferTokens: a non-zero token and amount, non-zero recipient bytes32, known non-source destination, and an arbiter fee no greater than the submitted amount.

The emitted bridge_transfer preserves the submitted ERC-20 amount, raw Wormhole destination id, configured EVM destination chain, raw recipient bytes32, requested arbiter fee, nonce, and outer attached value. recipient is exposed only when the bytes32 is a canonical zero-left-padded non-zero EVM address; other forms remain recipientEncoding: 'opaque-bytes32'.

This represents only the origin-chain request. The parser does not normalize the amount to Wormhole's VAA precision, predict a core-message fee, assert a lock/burn or mint/release, identify a destination token, calculate a paid fee, or claim destination delivery. transferTokensWithPayload intentionally stays generic because its payload can drive arbitrary destination contract logic. wrapAndTransferETH forms also stay generic: calldata contains no standalone bridged amount, and the payable value includes state-dependent Wormhole fees.

Wormhole Native Token Transfers (NTT) requests

Register every trusted NTT Manager with its source asset and each permitted uint16 Wormhole-chain-id-to-EVM-chain binding. The parser does not read the Manager's token() state, proxy implementation, receipt logs, or RPC: an unbound Manager, asset, or destination remains an ABI-decoded generic call.

Both direct transfer overloads are supported. The advanced overload retains the raw refund bytes32, shouldQueue, and opaque transceiverInstructions; it exposes the recipient or refund address only when their bytes32 values are canonical zero-left-padded non-zero EVM addresses. The action's amount is the submitted request, not a promise of the final token amount: fee-on-transfer behavior and transfer trimming are contract execution details.

An NTT action is an origin-chain request only. It does not assert whether the request was queued, later cancelled, attested, delivered, minted, released, or refunded; nor does it price attachedValue or interpret transceiver instructions. Consumers should render those raw fields for review rather than turn them into fee or delivery claims.

Hyperlane Warp Route requests

Register each trusted Hyperlane Warp Route TokenRouter with a source asset and every permitted uint32 domain-to-EVM-chain binding. Neither comes from transferRemote calldata: a Warp Route can be a native, collateral, or synthetic implementation, and Hyperlane supports non-EVM domains. The parser therefore never identifies an asset from the router's address or assumes a domain is an EVM chain id.

The direct transferRemote(uint32,bytes32,uint256) route emits the submitted source amount, configured source asset, raw destination domain, configured EVM destination chain, raw recipient bytes32, and outer attached value. A canonical zero-left-padded non-zero EVM bytes32 additionally exposes recipient; other recipient encodings remain opaque.

This is an origin-chain transfer request, not a statement that collateral was locked, a synthetic was burned or minted, a native asset was delivered, or a message was relayed. Warp Route, relayer, security, and external-bridge fees are quote/state dependent; attachedValue is retained exactly and never treated as a fee or an asset amount. Unconfigured routers or domains remain generic ABI-decoded contract calls.

Axelar Interchain Token Service requests

Register every trusted ITS deployment with two explicit application-owned maps: Axelar's exact destination-chain string to an EVM chain id, and ITS bytes32 token id to the source asset address. Neither mapping is recovered from the ITS address, the transaction, a receipt, token metadata, or RPC.

The parser recognizes the direct four-argument interchainTransfer(bytes32,string,bytes,uint256) path and the deprecated six-argument form only when its metadata is exactly empty. Both emit the token id, configured asset, exact Axelar destination string, configured EVM destination id, amount, raw recipient bytes, requested gas value, and outer attached value. The recipient is exposed as an EVM address only when the raw bytes are exactly one non-zero 20-byte EVM address; all other encodings stay opaque. Metadata-bearing calls can execute a destination contract and remain generic ABI-decoded contract calls.

This is an origin-chain transfer request only. requestedGasValue and attachedValue are retained separately; the parser does not infer a paid fee, refund, token lock/burn, destination asset, relay status, or destination delivery. Unknown token ids, destination strings, and ITS deployments stay generic rather than being guessed.

Arbitrum L1 Inbox native deposits

Register a trusted Arbitrum L1 Inbox and its explicit EVM destination chain. The parser recognizes only payable depositEth() with a positive outer value. It emits a native bridge_transfer request whose recipient is the transaction sender, matching this direct Inbox entrypoint. It does not assert sequencer inclusion, L2 execution, or destination crediting.

Retryable-ticket methods, arbitrary L2 calldata, ERC-20 gateway routes, and unconfigured Inbox addresses remain generic calls. This keeps the direct no-argument deposit surface separate from operations whose target execution or token mapping cannot be proved by calldata alone.

Arbitrum L1 Gateway Router ERC-20 deposits

Register each trusted L1 Gateway Router with its source and destination EVM chains. The parser recognizes only direct six-argument outboundTransfer(address,address,uint256,uint256,uint256,bytes) requests whose outer value is positive and whose retryable-ticket data is the canonical abi.encode(uint256 maxSubmissionCost, bytes emptyCallHookData) form. It preserves the explicit L1 asset, amount, sender, recipient, maxGas, gasPriceBid, maxSubmissionCost, and outer retryableFeeBudget separately.

The attached value funds the retryable ticket; it is not bridged ETH and is never folded into the ERC-20 amount. A non-empty call hook could execute arbitrary L2 logic, so it deliberately remains an ABI-decoded generic contract call. The parser also does not infer the L2 token mapping, escrow result, retryable-ticket creation or execution, destination delivery, or finality.

Arbitrum ArbSys native withdrawals

Register each trusted ArbSys precompile with both its source and destination EVM chains. The parser recognizes only payable withdrawEth(address) calls with a non-zero outer value and non-zero recipient. It emits the native amount, source chain, configured destination chain, sender, and recipient as an origin-chain bridge_transfer request.

The canonical ArbSys address alone is not a destination-chain binding: it is shared by Arbitrum deployments and does not make an Orbit chain's L1 target safe to guess. The parser therefore never registers this route implicitly. It does not assert L2-to-L1 message inclusion, proof, L1 execution, final receipt, or crediting. Zero-value calls, unconfigured addresses, malformed recipients, and same-chain configurations remain generic calls or configuration errors.

Arbitrum L2 Gateway Router ERC-20 withdrawals

Register each trusted L2 Gateway Router with its source and destination EVM chains. The parser recognizes only the direct four-argument outboundTransfer(address,address,uint256,bytes) path when outer value is zero and the supplied extra data is exactly empty. It preserves the explicit L1 token address, amount, sender, and recipient as an origin-chain withdrawal request.

The router calculates the local L2 counterpart internally. Therefore the parser calls the calldata token l1Token rather than guessing a local token address or token metadata. It does not assert escrow, L2-to-L1 inclusion, proof, L1 execution, final receipt, or asset crediting. Non-empty data and non-zero value are deliberately generic fallbacks because the canonical direct gateway path rejects those forms.

Hashflow RFQ-t single-hop swaps

Register each trusted legacy Hashflow Router explicitly. The parser recognizes only the same-chain tradeSingleHop RFQ-t quote shape, preserving the pool, trader, effective trader, base/quote tokens, exact effective input, original quoted base/output amounts, quote expiry, nonce, and quote id. The token recipient is the calldata trader; effectiveTrader is retained separately because the protocol uses it for quote nonce tracking.

Native input is recognized only when baseToken is the zero address and outer value exactly equals effectiveBaseTokenAmount. ERC-20 input requires zero outer value. If the quote is only partially used, exactQuotedOutput is false: the parser preserves the signed quote fields but does not present an inferred final output amount. It also does not verify the maker signature, look up pool or Router code, retrieve token metadata, or claim execution/fill success.

Cross-chain RFQs, multi-hop paths, missing/empty signatures, malformed quote identifiers, unconfigured Routers, and any payment form that does not exactly match these rules remain ABI-decoded generic calls. The parser makes no RPC or Hashflow API requests.

Polygon PoS RootChainManager deposits

Register each trusted Polygon PoS RootChainManager and its destination EVM chain explicitly. The parser recognizes only direct payable depositEtherFor(address) and zero-value depositERC20ForUser(address,address,uint256) calls. It preserves the source asset, exact submitted amount, recipient, source/destination chain ids, and outer attached value as a bridge_transfer request.

The RootChainManager calldata does not identify the mapped child-chain token, so every result intentionally has destinationAssetMode: 'unresolved' rather than inventing an L2 token address. No canonical RootChainManager address, child-token mapping, checkpoint/finality state, token metadata, or RPC lookup is assumed. Calls with unexpected native value, zero amount/address, or an unconfigured deployment remain generic ABI-decoded contract calls.

Fraxswap Multihop swaps

Register the trusted Fraxswap Multihop Router explicitly. The parser recognizes the direct swap(FraxswapParams) call only when the route bytecode is non-empty and its embedded permit fields are all zero. It preserves native/ERC-20 input and output forms, exact input amount, minimum output, recipient, deadline, route byte length, and outer attached value. Native input requires tokenIn == address(0) and exact equality between outer value and amountIn; ERC-20 input requires zero outer value.

The same ABI can carry an EIP-2612-style permit (approveMax, v, r, s). Those calls deliberately remain generic contract calls rather than being collapsed into a swap, so a wallet can review the authorization separately. The route itself is deliberately not interpreted: its pool topology and actual output remain protocol execution details. The parser does not validate route bytecode, discover pools/tokens, read prices, or make RPC calls.

Rubicon swaps

Register each trusted Rubicon Router with that deployment's exact wrappedNativeToken. The parser recognizes direct swap, swapForETH, and swapWithETH calls and retains the full token path, exact input amount, minimum output, recipient, configured wrapped-native token, and attached value. swapForETH uses the transaction sender as its recipient; it is classified as native output only if the final path token equals the configured wrapped token. Likewise, swapWithETH is native input only if the first path token matches and the outer value exactly equals payAmt.

The parser does not assume any canonical WETH address or interpret the middle of a multi-hop path. Empty/zero-address paths, mismatched wrapped-native endpoints, unexpected outer value, and unknown Router deployments remain generic ABI-decoded contract calls. It does not inspect order-book liquidity, quote execution, token metadata, prices, or RPC state.

Yield Yak swaps

Register each trusted Yield Yak Router explicitly. The parser recognizes direct swapNoSplit, swapNoSplitFromAVAX, and swapNoSplitToAVAX requests only when the encoded Trade has a non-zero token path, exactly one non-zero adapter per path hop, a positive exact input amount, and a non-zero recipient. It preserves the submitted token path, adapter addresses, minimum output, fee value, and attached value. The native-named input entrypoint requires attached value equal to amountIn; the native-output entrypoint requires zero attached value.

The native forms are classified from the trusted Router's explicit ABI entry points—not from a global wrapped-native-address table. The parser does not attest to adapter allowlists or behavior, inspect pools, calculate a quote, infer the eventual fill, resolve token metadata, or make RPC calls. Structural violations, unexpected outer value, and unknown Router deployments remain generic ABI-decoded contract calls.

Ambient/CrocSwap hot-path swaps

Register the trusted Ambient/CrocSwap Dex explicitly. The parser recognizes the direct hot-path swap and userCmd(1, abi.encode(swapArgs)) form, after preserving its base/quote pair, pool index, isBuy, inBaseQty, fee-rate limit, Q64 price limit, and settlement flags. It derives exact: 'in' only when the fixed qty is the paid side; the complementary two direction/quantity combinations are represented as exact: 'out', where minOut is the encoded maximum input limit. Other userCmd callpaths remain generic contract calls.

Ambient may use a virtual token address for the native asset. The parser never assumes that convention: nativeToken must be set for this exact trusted Dex before the corresponding base or quote address is labeled native. Native input also requires outer value to exactly equal the fixed input amount (or encoded maximum input for an exact-output request); all ERC-20 input forms require zero outer value.

Settlement flags can select protocol-specific accounting such as surplus balances, so they are preserved verbatim rather than interpreted. The parser does not query pool state, validate the eventual fill, calculate a price, resolve token metadata, or make RPC calls. Native virtual tokens without the explicit configuration, malformed calls, unexpected value, and unconfigured Dex addresses remain generic ABI-decoded contract calls.

Polygon zkEVM Bridge native deposits

Register a trusted Polygon zkEVM Bridge together with every permitted destinationNetwork to EVM chain-id mapping. The parser recognizes only the native bridgeAsset form: zero token, empty permitData, a positive amount, and outer value exactly equal to that amount. It preserves the recipient, amount, destination network id, configured EVM destination, and the forceUpdateGlobalExitRoot request.

Bridge network ids are protocol identifiers, not EVM chain ids. An unknown id therefore remains a generic contract call instead of falling back to a global chain table. ERC-20 bridgeAsset forms can require destination wrapped-token state, and permit-bearing forms contain an authorization operation; both remain generic calls. The parser does not infer these mappings, update an exit root, or claim bridge finality/delivery.

WOO Network swaps

Register each trusted WOO Network Router explicitly. The direct swap action preserves its exact input amount, minimum output, recipient, optional rebate recipient, and attached value. Some deployments encode native assets using an address sentinel instead of the zero address; provide that exact sentinel in nativeTokenSentinel if and only if the integration has trusted deployment metadata for it. The parser then requires exact outer value for native input and labels the configured sentinel as native on either side of the swap.

Without that opt-in configuration the same address remains an ordinary token address. The parser does not assume a canonical sentinel, execute a quote, price the output, or make any network request. Unexpected attached value and unconfigured Router addresses remain generic ABI-decoded calls.

OP Stack Standard Bridge deposits

Register the exact L1 Standard Bridge and its destination chain. The parser then recognizes only the direct depositETH, depositETHTo, depositERC20, and depositERC20To request ABIs. Its bridge_transfer action contains the native or L1 ERC-20 asset, the calldata-supplied L2 token representation for ERC-20 deposits, recipient, amount, source/destination chain ids, minimum gas limit, and the byte length of _extraData.

The configured source bridge and destination chain are mandatory. An ERC-20 deposit must have zero outer native value; native deposits must have a positive outer value. _extraData is intentionally not decoded: the Standard Bridge documents it as off-chain-only data rather than L2 executable calldata. This models the submitted bridge request only, never L2 execution, finality, token metadata, token equivalence beyond the supplied address pair, or delivery.

Withdrawals, arbitrary portal deposits, custom bridges, and transaction execution paths that require contract state remain generic calls. No canonical bridge address, L2 predeploy, token mapping, RPC lookup, or network I/O is assumed.

OP Stack Portal plain ETH deposits

Register each trusted low-level OP Stack Portal and its explicit destination chain. The parser recognizes only depositTransaction calls that are a plain positive-value ETH deposit: non-zero recipient, no contract creation, empty L2 calldata, a valid empty-call L2 gas limit, and exact equality between outer msg.value and calldata _value.

The result preserves the Portal, recipient, exact native amount, source and configured destination chains, L2 gas limit, and outer attached value. A Portal's _value is distinct from its outer msg.value; by requiring equality this specialized action cannot mislabel a partially funded or otherwise more complex deposit as a simple transfer.

Any non-empty _data may execute arbitrary L2 logic; _isCreation can deploy an L2 contract; and a contract caller can be address-aliased on L2. Those forms remain ABI-decoded generic contract calls. The parser does not assert lockbox or custom-gas-token state, L2 execution, finality, delivery, refunds, or an L2 transaction hash.

zkSync BridgeHub plain native self-deposits

Register the exact BridgeHub and every permitted protocol-destination-id to EVM-chain-id binding. The parser recognizes only requestL2TransactionDirect calls that are unambiguously a native self-deposit: the outer ETH value exactly equals mintValue, the L2 target and refund recipient both equal the transaction sender, l2Calldata is empty, and there are no factory dependencies. It also requires positive mint/L2 values and gas parameters.

The resulting bridge_transfer preserves the total submitted mintValue, the L2 call value, both gas parameters, the configured destination, and the raw BridgeHub destination id. It deliberately does not derive or label a fee from the difference between mintValue and l2Value, since actual execution and refund behavior are protocol state.

BridgeHub can dispatch arbitrary L2 calls and chains may u