# Balance-delta inflation via hooks and self-transfers

Accounting that trusts balanceOf deltas or caller-supplied amounts around transfers with hooks, self-transfers, or batch reuse

_Area: DeFi accounting and math bugs. Seen in 3 disclosed reports; latest 2024-02-13. Updated 2026-11-02._

## How it works
Code measures "how much moved" as `balanceAfter - balanceBefore` on one side of a transfer, or trusts an amount the caller supplies. That assumption breaks when something else changes the measured balance during the same call, or when the transfer never really costs the sender anything. The recorded amount then exceeds what actually moved, and downstream bookkeeping (flow limits, swap outputs, bribe amounts) drifts from reality.

## Where it shows up
- Any `_giveToken`/`_processTx`-style helper returning `balanceOf(to)` delta after a transfer [E2](https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-02.md)[E1](https://bugbountylibrary.com/r/cantina%3Asuperform_erc1155a_dec2023%3A3.2.10.md).
- Batch or looped swap processors that measure only the output token per iteration [E1](https://bugbountylibrary.com/r/cantina%3Asuperform_erc1155a_dec2023%3A3.2.10.md).
- Tokens with receiver hooks (ERC777 `tokensReceived`, ERC677) or rebasing behavior feeding delta math [E2](https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-02.md).
- `safeTransferFrom` where `src == dst` is allowed; WETH skips allowance deduction in that branch [E3](https://bugbountylibrary.com/r/c4%3A2022-02-redacted-cartel%3AM-16.md).
- Contracts recording an amount from a caller-supplied `briber`/`from` address without rejecting `address(this)` [E3](https://bugbountylibrary.com/r/c4%3A2022-02-redacted-cartel%3AM-16.md).

## How to review
State the invariant: the recorded amount must equal tokens that actually left the payer and cannot be re-counted within one operation. Check:
- Does the accounting track both sides (source decrease and target increase), not just output? [E1](https://bugbountylibrary.com/r/cantina%3Asuperform_erc1155a_dec2023%3A3.2.10.md)
- Can the receiver's balance change mid-transfer via a hook before the delta is read? [E2](https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-02.md)
- Is `src == dst` rejected, and is the payer address validated against the vault itself? [E3](https://bugbountylibrary.com/r/c4%3A2022-02-redacted-cartel%3AM-16.md)
- Across a batch, is each unit of liquidity consumed once, or can alternating swaps recycle it? [E1](https://bugbountylibrary.com/r/cantina%3Asuperform_erc1155a_dec2023%3A3.2.10.md)

## How finders spotted it
- Read `_processTx` and noticed it only checks target-token increase, never the source-token decrease, so liquidity could be reused across swaps in one payloadId [E1](https://bugbountylibrary.com/r/cantina%3Asuperform_erc1155a_dec2023%3A3.2.10.md).
- Read `_giveToken`'s balance-delta logic alongside knowledge that ERC777 fires a receiver hook that can mutate the receiver's balance before the delta is computed [E2](https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-02.md).
- Read WETH's `transferFrom` and saw allowance deduction sits inside the `src != msg.sender` branch, so self-transfer bypasses allowance; combined with the vault accepting an arbitrary briber [E3](https://bugbountylibrary.com/r/c4%3A2022-02-redacted-cartel%3AM-16.md).

## Variants seen
- Batch swap processor counting output-only deltas, recycling liquidity across swaps [E1](https://bugbountylibrary.com/r/cantina%3Asuperform_erc1155a_dec2023%3A3.2.10.md).
- Receiver hook inflating its own balance to over-count flow-in and DoS a flow limit [E2](https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-02.md).
- Self-transfer with a token that short-circuits allowance, inflating a recorded amount for free [E3](https://bugbountylibrary.com/r/c4%3A2022-02-redacted-cartel%3AM-16.md).

## Impact and severity
E1 lets an attacker inflate `swappedAmount` and drain DstSwapper liquidity, scaling with the number of swaps and payloadIds [E1](https://bugbountylibrary.com/r/cantina%3Asuperform_erc1155a_dec2023%3A3.2.10.md). E2 over-counts flow-in and can DoS the bridge flow limit [E2](https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-02.md). E3 lets a privileged depositor inflate bribe amounts at no cost [E3](https://bugbountylibrary.com/r/c4%3A2022-02-redacted-cartel%3AM-16.md). Severity rises with how much value the inflated number controls and whether the path is repeatable or permissionless.

## Evidence
- E1: https://bugbountylibrary.com/r/cantina%3Asuperform_erc1155a_dec2023%3A3.2.10.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-02.md
- E3: https://bugbountylibrary.com/r/c4%3A2022-02-redacted-cartel%3AM-16.md
