Skip to main content
One cross-chain transfer, one row. Sending a token from one chain to another leaves an event on the chain it departs from and another on the chain it arrives at, and facts.bridge_transfers pairs those two sides into that single row. Each side is called a leg. Where only one leg turns up, the row carries the leg it has and says why the other is missing. The table puts LayerZero v1 and v2, Circle CCTP v1 and v2, and Chainlink CCIP onto the same columns, matching each bridge’s legs on identifiers of its own, with token amounts and USD values worked out once before publication. A row is keyed on the onchain identity of whichever leg it is anchored on: the source leg for a matched pair or a departure with no arrival, the destination leg for an arrival with no departure.

Columns

ColumnTypeDescription
block_timestampTIMESTAMPThe column the table is partitioned on: the sending leg’s time, or the arriving leg’s where there is no sending leg.
project_idSTRINGProject operating the bridge.
product_idSTRINGVersion of the bridge within that project.
app_idSTRINGBridge app: layerzero-v1, layerzero-v2, circle-cctp-v1, circle-cctp-v2 or chainlink-ccip.
match_keySTRINGThe identifier the two legs were paired on, provided by the bridge.
match_methodSTRINGexact on matched rows, empty otherwise.
latency_secondsINT64How long the transfer took, in seconds. Empty on unmatched rows.
unmatched_reasonSTRINGWhy the other leg was not found. Empty on matched rows.
intermediary_addressSTRINGAddress of the relayer that carried the message. Empty on every row.
source_chain_idSTRINGChain the transfer left. Empty where no sending leg was found.
source_transaction_hashSTRINGTransaction the sending leg was in.
source_log_indexINT64Position of the sending event within its block.
source_sub_log_indexINT64Which token, within a sending event that moved more than one. Zero everywhere except CCIP sending legs.
source_block_timestampTIMESTAMPTime of the block the transfer left in.
source_block_numberINT64Number of that block.
source_sender_addressSTRINGAddress that sent the transfer.
source_recipient_addressSTRINGWho the sending leg says should receive it.
source_token_addressSTRINGToken contract on the chain it left.
source_token_idSTRINGThat token’s key in dimensions.tokens. Empty where we do not carry the token.
source_bridge_contract_addressSTRINGBridge contract the sending event came from.
source_amount_rawBIGNUMERICAmount leaving, in the token’s smallest units, before decimals are applied.
destination_chain_idSTRINGChain the transfer arrived on. Empty where no arrival was found.
destination_transaction_hashSTRINGTransaction the arriving leg was in.
destination_log_indexINT64Position of the arriving event within its block.
destination_block_timestampTIMESTAMPTime of the block the transfer arrived in.
destination_block_numberINT64Number of that block.
destination_sender_addressSTRINGSender named on the arriving leg.
destination_recipient_addressSTRINGAddress that received the transfer.
destination_token_addressSTRINGToken contract on the chain it arrived on.
destination_token_idSTRINGThat token’s key in dimensions.tokens. Empty where we do not carry the token.
destination_bridge_contract_addressSTRINGBridge contract the arriving event came from.
destination_amount_rawBIGNUMERICAmount arriving, in the token’s smallest units, before decimals are applied.
source_transfer_amountFLOAT64Amount leaving, in whole token units.
source_transfer_amount_usdFLOAT64Amount leaving, in USD.
destination_transfer_amountFLOAT64Amount arriving, in whole token units, with the fallback described above.
destination_transfer_amount_usdFLOAT64Amount arriving, in USD, with the same fallback.
transfer_amountFLOAT64The transfer counted once, in whole token units: the sending side’s amount, or the arriving side’s where there is no sending leg.
transfer_amount_usdFLOAT64The transfer counted once, in USD. Total volume by summing this column, never by adding the two directional columns.

Sample queries

The table is partitioned on block_timestamp. Put a filter on that column in every query. Leave it out and the query reads every day we hold.
Total daily bridged USD volume per app, counting each transfer once. transfer_amount_usd takes the sending side’s value, or the arriving side’s where there is no sending leg, so every transfer contributes exactly once.

Notes

Every transfer has a sending side and an arriving side, and this table values both. source_transfer_amount_usd is the money leaving. destination_transfer_amount_usd is that same money arriving. Add the two columns together and you have counted the same money twice. To total volume, use transfer_amount_usd, or transfer_amount for token units. Each takes the sending side’s value, falling back to the arriving side’s where there is no sending leg, so a transfer counts exactly once however many legs were found. Use the two directional columns only when you want to credit volume to the chain it left or the chain it reached. destination_transfer_amount and destination_transfer_amount_usd describe the money arriving. Each carries the arriving leg’s own amount where the event states one. Some bridges do not state it, CCIP’s arrival event among them, so where the row is matched but the arriving event names no amount, these columns fall back to the sending side’s value. Where no arriving leg was found at all, both stay empty. The legs are paired on match_key, an identifier each bridge provides of its own, such as LayerZero’s GUID or CCIP’s message id, with the arriving leg required to fall within a window around the sending leg’s time. match_method reads exact on a matched row and is empty otherwise. latency_seconds is how long the transfer took: the arriving block’s time minus the sending block’s. block_timestamp, the column the table is partitioned on, is the sending leg’s time, or the arriving leg’s where there is no sending leg. unmatched_reason is empty on a matched row and says what went wrong on every other one. A row with a sending leg but no arrival reads source_key_missing, destination_chain_not_indexed, destination_leg_not_decoded or destination_pending_or_failed. A row with an arrival but no sending leg has the mirror image: destination_key_missing, source_chain_not_indexed, source_leg_not_decoded or source_leg_missing.