# Measured, not nominal: why a protocol must never trust the number it passed to a token

> Canonical: https://blazephoenix.xyz/learn/measured-not-nominal
> License: CC BY 4.0 (attribution + link) · © 2026 BlazePhoenix
> Updated: 2026-07-29

A transfer of 100 does not mean 100 arrived: fee-on-transfer, rebasing and non-conforming tokens break any protocol that credits the requested amount. The general fix is a discipline — measure the balance delta and treat it as the only truth, on intake and on payout.

Almost every integration bug at the asset boundary reduces to one sentence: the protocol believed the number it asked for instead of the number that arrived. The token standard makes that belief feel safe — you call transfer with an amount, the call succeeds, so the amount moved. In practice the standard is a suggestion, and a large family of deployed tokens does not honour it in the way integrators assume.

## Four ways the number lies

FEE-ON-TRANSFER. The token deducts a fee inside the transfer, so the recipient receives strictly less than was sent. A protocol that credits the requested amount is now over-credited against real holdings, and every downstream calculation inherits the error. This is not theoretical: a fee-on-transfer token was used to drain roughly half a million dollars from pools whose accounting assumed the nominal figure.

REBASING. Balances change with no transfer at all — the supply is adjusted and every holder's number moves. A protocol that snapshots a balance and assumes it is stable until it acts will be wrong by the time it acts, in either direction.

NON-CONFORMING RETURNS. Widely-held tokens return no boolean at all from transfer, so a naive integration reverts on decoding; and at least one prominent token declares a boolean and returns FALSE on a transfer that in fact succeeded. Checking the return value naively is as broken as not checking it.

REENTRANT HOOKS. Token standards with transfer callbacks hand control to the counterparty in the middle of a movement, so state read before the transfer can be stale by the line after it.

## The discipline: the delta is the only truth

The general fix is not a list of token-specific special cases — it is a rule applied uniformly at every boundary: read the balance before, perform the movement, read the balance after, and treat the DIFFERENCE as the amount. Never the argument you passed.

Applied consistently, it removes the whole family at once. Fee-on-transfer stops mattering because the fee is inside the delta. Rebasing stops mattering because the delta is computed across the same window as the movement. A token that lies about its return value is caught because the balance either moved or it did not — and unlike a return value, a balance cannot be faked without capital.

The rule extends to the payout side, which integrators forget more often than the intake side. If a protocol promises a user a minimum output, that promise must be enforced on what the user ACTUALLY RECEIVED, not on the amount the protocol nominally sent. Otherwise a deflationary token quietly slips the user below their own bound while the protocol reports success.

> equation: received := balanceOf(this)ₐfₜₑᵣ − balanceOf(this)befₒᵣₑ // never the argument — The measured-delta rule at every asset boundary: intake, payout and any intermediate hop. A balance cannot be faked without capital; a return value can.

## The second-order trap: a guard calibrated on fiction

Here is the failure that survives a naive fix. Suppose the protocol adopts the delta rule for accounting but keeps a safety check — a minimum-output floor, say — that was derived from a quote computed as though no transfer fee existed. The accounting is now correct and the guard is now wrong: it demands an output the token can never deliver, so it rejects a perfectly honest fill. The protocol has traded silent over-crediting for loud denial of service.

The resolution is that a guard must be calibrated on the same measured reality as the accounting. If a fee was OBSERVED during execution — not declared by the caller, not guessed from a list, but measured — the fee-blind component of the floor is the wrong instrument for that trade and must yield to the bounds that are computed from real amounts. The user stays protected by their own explicit minimum and by a floor derived from what genuinely arrived; nothing is relaxed for honest tokens, whose behaviour is unchanged because their measured delta always equals the nominal amount.

## Why this is an invariant problem, not a compatibility problem

It is tempting to file all of this under "token compatibility" and maintain an allowlist. That approach fails on contact with reality: the space of misbehaving tokens is open-ended, permissionless, and grows faster than any list. Worse, an allowlist is a claim about the world rather than a property of the code, and claims about the world are exactly what an adversary edits.

The measured-delta rule is different in kind. It is a local, checkable invariant that holds regardless of what the token does, because it observes the outcome rather than trusting the interface. A conservation guard computed on measured reality can then be honest: it compares the real balance change to the real change in what the ledger claims to owe, so a token that behaves strangely produces a rejected transaction rather than a quietly over-credited ledger. That is the difference between a protocol that hopes tokens are well-behaved and one that does not need them to be.

**Verify it yourself:** Take any integration and ask what it credits: the amount it passed, or the amount it measured — then run a fee-on-transfer token through it and compare its ledger to the real balance, because the gap between the two IS the bug

Related: https://blazephoenix.xyz/learn/invariant-driven-design · https://blazephoenix.xyz/learn/iron-floor · https://blazephoenix.xyz/learn/invariants-and-time
