Skip to content
Finality

Crypto protocol and market news

Fee-on-Transfer Bridge Deposits Need Balance-Delta Accounting

A bridge should credit the tokens its contract actually receives, then carry that measured amount through messaging, minting, and withdrawal accounting without overstating collateral.

The Finality Desk5 min read#e4a445

Cover artwork for Fee-on-Transfer Bridge Deposits Need Balance-Delta Accounting

A bridge handling a fee-on-transfer token should account for the balance increase its deposit contract actually receives, not the amount passed to transferFrom. The caller’s requested amount can exceed the bridge’s new collateral because the token deducts a fee during the transfer. If the bridge messages or mints against the request, its destination-side liability can exceed the assets backing it.

This distinction starts at the source-chain deposit. An ERC-20 transferFrom(address,address,uint256) call takes an amount argument, but a token with transfer fees can credit the recipient with less. The bridge can measure the difference between its balanceOf before and after the call, then use that delta as the deposit amount. A fuller explanation of the Mantle Bridge’s wallet-to-bridge path provides context for where that accounting step sits in a cross-chain transfer.

Why can the requested deposit differ from the amount received?

A fee-on-transfer token changes the balances affected by a transfer according to its own contract logic. A user can approve and request a deposit of 100 tokens, while the bridge’s balance rises by 98 after the token deducts a fee. The exact result depends on the token: its fee may be burned, sent to a fee recipient, or calculated under other token-specific rules.

The ERC-20 interface does not give the bridge a standard fee field or a standard “net received” return value. A successful call means the token call did not revert; it does not mean the bridge received the argument amount. A Transfer event is useful for tracing activity, but it may not represent a single transfer of the requested amount when a token emits separate events for the recipient and fee. The bridge’s own balance change is the relevant quantity for its collateral accounting, provided the token’s balanceOf is trustworthy.

How should the bridge calculate and record the deposit?

The deposit function should read the bridge’s token balance, call safeTransferFrom, read the balance again, and calculate the difference. It should validate that difference before recording the deposit or sending a cross-chain message. The amount in the deposit record and message must match the received delta, rather than the user’s requested amount.

  • Use the token’s balance immediately before the transfer as the baseline.
  • Pull the requested amount with transferFrom, handling tokens that return no value as well as those that return a boolean.
  • Read the balance again and subtract the baseline to find the amount received.
  • Use that measured amount for the deposit event, relay payload, and destination-side credit.

For a lock-and-mint bridge, the measured amount defines how much the bridge can safely represent on the destination chain. If the source contract receives 98 tokens, minting 100 wrapped tokens creates a two-token shortfall. If the destination representation also charges a fee when it is transferred to the recipient, the recipient may receive less than the amount minted; that is a separate transfer effect and should be made clear in the bridge’s accounting and user-facing amount.

For a burn-and-mint design, the same accounting question applies even though the source token is burned rather than held as escrow. The bridge must establish which amount the source contract actually accepts or burns and keep the destination mint amount consistent with that quantity. A fee charged during a user-to-bridge transfer cannot be ignored merely because the bridge later burns tokens.

What edge cases can break balance-delta accounting?

Balance-delta measurement is only as reliable as the token behavior it measures. Rebasing tokens can change balances outside a transfer, and reflection mechanics can credit holders as a side effect of activity elsewhere. A token could also return misleading values from balanceOf or behave differently when the bridge itself is the sender or recipient. The measured delta is therefore a sound accounting method for supported tokens, not a guarantee that every token can be bridged safely.

The bridge should define a token policy and enforce it at the deposit boundary. It can reject a zero received delta, enforce a minimum net amount supplied by the depositor, and use a reentrancy guard around the transfer and state update. If the bridge calls another contract or dispatches a message before recording the measured amount, a callback or failure path can leave the accounting inconsistent. The deposit record, emitted bridge event, and outbound message should all derive from the same validated delta.

Withdrawals need their own explicit rule. If the bridge unlocks a fee-on-transfer token by requesting 98 tokens, the recipient may receive less than 98, while the bridge’s balance falls by 98. The bridge should define whether its withdrawal amount means the gross amount debited from its reserve or the expected net amount delivered, then account for the token’s transfer fee accordingly. Deposit-side measurement alone does not settle that distinction.

The practical rule is straightforward: measure what enters, and base the cross-chain credit on that amount. Then define outbound amounts according to whether the bridge promises a gross debit or a net receipt. That keeps the collateral ledger aligned with the token’s actual behavior and makes the remaining fee visible in the transfer’s terms.