@ruban-labs/web3-tx-parser
v0.24.0
Published
Extensible TypeScript transaction intent parser for EVM calldata.
Maintainers
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-stylepermitwhen 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
safeTransferFromandsafeBatchTransferFromwhen the caller supplies trusted contract-standard context; - ERC-721/1155-style
setApprovalForAllwhen the caller supplies trusted NFT context; - direct WETH-compatible
deposit()andwithdraw(uint256)calls, only for explicitly configured wrapped-native deployments; - direct wstETH-style
wrap(uint256)andunwrap(uint256)calls, only for explicitly configured wrapper and underlying-token pairs; - ERC-4626
deposit,mint,withdraw, andredeem, only for explicitly configured vault and underlying-asset pairs; - Permit2 direct allowance
approve, signed single/batch allowancepermit, one-time signature transfer, andlockdown, only for explicitly configured Permit2 deployments; - Safe
execTransactionouter-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
swaprequests, 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
depositIntoStrategyanddepositIntoStrategyWithSignature, 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
exchangeandexchange_underlyingrequests, only for explicitly configured pools and caller-supplied coin-order bindings; - Across V3 SpokePool direct
depositV3bridge requests, only for explicitly configured SpokePools; native-input form additionally requires an explicit wrapped-native token and an empty destination message; - Connext direct
xcallbridge 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
transferTokensrequests, 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
transferrequests, 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
transferRemoterequests, only for explicitly configured TokenRouters, source assets, and Hyperlane-domain-to-EVM-chain bindings; - Axelar Interchain Token Service direct token-only
interchainTransferrequests, 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
outboundTransferdeposits, 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
outboundTransferrequests, only for explicitly configured routers and destination chains with zero outer value and empty extra data; - Hashflow legacy Router direct same-chain RFQ-t
tradeSingleHoprequests, only for explicitly configured Router deployments and complete signed quote calldata; - OrbiterRouterV3 direct native
transferand ERC-20transferTokenMaker 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
sendNativeand ERC-20sendliquidity-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
depositForBurnrequests, only for explicitly configured TokenMessenger deployments and explicit CCTP-domain-to-EVM-chain bindings; non-EVMbytes32recipients remain opaque; - Circle CCTP V2 direct no-hook
depositForBurnrequests, 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
sendrequests, 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
bridgeAssetrequests, 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
swapETHbridge requests, only for explicitly configured native routers and explicit Stargate-id-to-EVM-chain bindings; - Stargate V1 Router ERC-20
swapbridge 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
depositTransactionrequests, 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
sendToL2bridge 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, andcancelAuthorization, 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*andexactOutput*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_callfallback.
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:
- exact
contractaddress; - proxy
implementationcode id; - contract
codeid; - deployment
factoryaddress; defaultselector 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
