Asset-Identity Aliasing / Multi-Entry Token Surface

  • Name: asset-identity aliasing / multi-entry token surface
  • Category: exploit pattern / integration failure / asset-identity failure / token-alias surface / address-equality bypass
  • Summary: Many protocols quietly assume that one economic asset has one canonical contract address. That assumption leaks into allowlists, deny-lists, underlying != token guards, rescue hooks, accounting adapters, and collateral admission checks. The failure mode appears when the same balances or transfer logic are reachable through more than one address: a legacy forwarding token, an upgrade shim, a compatibility alias, or another dual-entry deployment. Once that happens, address-equality checks stop proving asset identity. A path that was supposed to exclude the underlying asset, or isolate unsupported assets, can be re-entered through the alias address and still mutate the same balance sheet. The exploit is not that the token has exotic transfer semantics. The exploit is that the protocol’s trust boundary says asset identity = address, while reality says one asset can answer through several addresses. The sharper review split is does this alias still reach the same balances?, does policy still mean the same protected asset once aliases are canonicalized?, and what helper authority was only supposed to exist for genuinely different assets?
  • What it is:
    • A protocol uses contract address equality as the entire proof that two token surfaces are different assets.
    • But one economic asset is exposed through multiple addresses that share balances, allowances, or transfer effects.
    • A helper or policy path that is safe only for non-underlying, non-listed, stray, or other tokens becomes reachable with an alias address.
    • The protocol then performs a privileged, unsupported, or solvency-critical action against the real asset while believing it is touching something else.
    • Loss occurs when the alias path can move real reserves, bypass an asset guard, or distort accounting that downstream mint / redeem / borrow logic still honors.

Three asset-identity questions reviewers should not collapse

1. Does this alias still reach the same economic balances?

  • The first question is mechanical: does the alternate address still read, move, or authorize the same balances, allowances, or transfer effects as the canonical token surface?
  • ChainSecurity’s and OpenZeppelin’s TUSD / Compound writeups preserve the clean answer: the legacy TUSD address and the newer TUSD address still touched the same balances, so different address never meant different reserve.
  • If teams skip this step, they start arguing about policy before they have even proved whether the alias is economically separate.

2. Once canonicalized, does policy still mean the same protected asset?

  • The second question is policy meaning: after collapsing every alias to one asset object, should underlying, listed, paused, unsupported, rescuable, or cannot sweep still evaluate the same way?
  • Compound’s mistake was not merely that TUSD had a second address. The mistake was that cannot sweep underlying was keyed to one preferred address rather than to the whole TUSD asset family.
  • This is the review point where address equality has to give way to canonical asset identity.

3. What authority was only supposed to exist for genuinely different assets?

  • The third question is helper authority: which exact rescue, sweep, adapter, routing, or treasury-management action only becomes safe if the supplied token is truly a different asset rather than an alias?

  • In Compound’s case, sweepToken() looked like housekeeping only because it was supposed to operate on stray assets. Once the alias bypass succeeded, it inherited reserve-moving authority over the live TUSD cash that priced cTUSD.

  • If teams collapse this into the first two questions, they may correctly identify aliasing and still understate why the helper was dangerous enough to become a solvency primitive.

  • The practical discipline is to answer all three in order: does the alias still reach the same balances?, does policy still protect the same asset after canonicalization?, and what helper authority should disappear once the alias is recognized as the same asset?

  • Typical preconditions:

    • The token has a legacy forwarding contract, compatibility shim, migration facade, proxy-era alias, or another double-entry architecture.
    • Integrators whitelist, blacklist, or special-case assets by raw address equality alone.
    • The protocol exposes a generic token helper such as sweepToken, rescue, adapter routing, or arbitrary-token interaction that is assumed safe for any token except the underlying.
    • The economic consequences of moving or re-reading balances through the alias are not re-validated against an asset-specific invariant.
    • The protocol lacks a canonicalization layer that collapses all known aliases to one asset identity before policy is checked.
  • Common vulnerable surfaces:

    • lending-market sweepToken or rescue-token hooks
    • vault / adapter systems that exclude or special-case one asset by address only
    • bridge or wrapper registries that believe an alias address implies a distinct asset domain
    • permissionless helper functions that accept arbitrary token addresses and assume different address => different asset
    • collateral or treasury systems that let an alias bypass unsupported asset checks and still touch the same balance sheet
  • Exploit sequence:

    1. The attacker finds an asset whose balances or transfers can be reached through more than one contract address.
    2. They identify a protocol path whose safety relies on address(token) != canonicalAddress or a similarly narrow address-based guard.
    3. They call that path with the alias address instead of the canonical one.
    4. The protocol accepts the alias as a different asset.
    5. The alias call still mutates or observes the same real balances, reserves, or allowances as the canonical asset.
    6. The helper or policy exception performs an action that should have been impossible for the real asset.
    7. The attacker monetizes the resulting reserve movement or accounting distortion through mint, redeem, borrow, liquidation, or governance side effects elsewhere in the system.
  • Variants:

    • Underlying-exclusion bypass — a generic token rescue path blocks the configured underlying address but not an alias that still controls the same balance sheet. TUSD is the canonical exemplar.
    • Unsupported-asset alias admission — a system thinks it is interacting with a different or unsupported token surface, but the alias still mutates the supported asset’s balances or allowances.
    • Policy split across aliases — one address inherits stricter controls, pauses, or quarantine, while another alias still exposes economically equivalent authority.
    • Bookkeeping helper becomes solvency primitive — a token-rescue or migration helper that looks operational only becomes financially critical because the alias touches reserves that price live claims.
  • Detection heuristics:

    • Ask whether any integrated asset has legacy wrappers, forwarding contracts, proxies, shims, or documented alternate entry points.
    • Review every token != underlying, unsupported[token], listed[token], rescue(token), or sweepToken(token) policy and ask whether an alias could satisfy the check while still touching the same balances.
    • Treat asset identity as broader than address whenever a token’s architecture predates modern proxy norms or explicitly supports migration compatibility.
    • Compare balanceOf, transfer, and allowance behavior across all documented token entry points to see whether two addresses map to one economic object.
    • Re-run threat modeling for housekeeping functions; if a helper can move balance-sheet-critical cash through an alias, it is not merely operational code.
  • Defenses:

    • Canonicalize asset identity before policy checks: collapse known aliases, forwarders, wrappers, or migrated entry points to one asset identity object.
    • Prefer invariant checks over address checks for rescue paths; for example, prove that sweeping a candidate token does not change underlying economic exposure.
    • Keep generic token-rescue hooks permissioned or heavily constrained when the asset universe contains upgrade shims or legacy aliases.
    • Maintain per-asset integration dossiers that include alias surfaces, not just the preferred address.
    • Test listed assets against alternate entry points and require that non-underlying checks remain true under those aliases.
    • When possible, fix the root cause at the token layer by disabling or narrowing dangerous legacy entry points instead of only hardening one integrator.

What sound design looks like

  • A healthy integration treats asset identity as a first-class object that happens to have one or more callable token surfaces, not as a synonym for whichever address the listing code happened to store first.

  • Healthy review preserves three separate answers: this alias still reaches the same balances, this policy still protects the same canonical asset, and this helper has no authority once the supplied token is recognized as that same asset after all.

  • Every policy that matters economically — underlying, listed, paused, rescuable, unsupported, collateral-eligible, sweepable — should evaluate against that canonical asset object before any helper, adapter, or rescue logic decides what authority it has.

  • Helper paths should prove the protected invariant directly. If a sweepToken() or rescue path is only safe when it cannot touch the reserve backing live claims, the code should prove this action cannot change reserve truth rather than merely prove caller supplied a different address.

  • Alias families should share one lifecycle state. If the canonical token is paused, quarantined, deprecated, or exit-only, every alias that can still reach the same balances should inherit the same restriction instead of remaining a forgotten side door.

  • Residual or legacy token surfaces should be narrowed like any other leftover authority surface. If a forwarding contract or compatibility shim is no longer needed for ordinary operation, either disable it upstream or treat it as live production risk with the same monitoring and policy as the canonical asset.

  • Tests should compare asset-level invariants, not just address-level allowlists. A strong suite proves that alternate entry surfaces cannot change reserves, exchange rates, collateral value, or treasury state in ways the canonical surface would forbid.

  • Integrations should maintain an explicit asset dossier: canonical address, alias addresses, which functions each alias still exposes, whether balances and allowances are shared, and which policy object governs the whole family. Without that inventory, address-based safety checks will drift back in.

  • Design contrasts worth preserving:

    • Not ordinary token-semantics mismatch — interface-conformance semantic-compatibility failure is about assets whose behavior violates deeper semantic assumptions like passive transfers or exact amounts. This note is sharper: the behavior can be ordinary, but the protocol is wrong about which address names the asset.
    • Not counterfeit collateral admission — counterfeit-collateral admission covers admitting the wrong economic asset as collateral. This note covers the same economic asset appearing through multiple addresses and thereby bypassing identity-based policy.
    • Not bridge denomination poisoning — asset-identity registry poisoning is about registries lying about which custody asset a denom redeems. This note is about aliasing within one token’s onchain entry surface.

Failure-prevention checklist

  • Build a canonical asset-identity layer before any policy check. underlying, listed, paused, rescuable, and unsupported decisions should evaluate a canonical asset object, not a raw token address.
  • Maintain an alias inventory for every integrated asset, including legacy forwarders, migration shims, proxy-era entry points, wrapper facades, and deprecated surfaces that still share balances, allowances, or transfer effects.
  • Preserve the three-step review ladder in tests and code review: prove which aliases still reach the same balances, prove that canonicalized policy still protects the same asset family, then prove that helper authority disappears once that alias family is recognized as protected.
  • Treat rescue, sweep, arbitrary-token adapter, and migration helpers as solvency code whenever they can touch reserves or accounting inputs that price live claims.
  • Require every token != underlying, listed[token], unsupported[token], and similar guard to prove the same answer under every known alias of the protected asset.
  • Prefer invariant-based allow rules for housekeeping functions: a candidate token operation must prove it cannot change protected reserve balances or protected economic exposure, rather than merely proving address != canonicalAddress.
  • Add integration tests that execute helper paths through alternate token entry points and confirm reserves, exchange rates, collateral value, and treasury balances cannot move unexpectedly.
  • Keep pause, quarantine, and deauthorization state attached to the asset identity, not only to one address. A deprecated alias should not stay economically live after the main address is paused.
  • Push root-cause fixes upstream when possible: disable, deprecate, or permission legacy alias surfaces instead of assuming every downstream integrator will remember them forever.
  • Require integration dossiers for nontrivial assets to document alias surfaces explicitly before listing, collateral admission, or treasury use.
  • Monitor for reserve-affecting balance changes or token movements initiated through addresses that the protocol did not classify as the canonical asset surface.

Audit prompts

  • Which integrated assets have more than one onchain entry point that can reach the same balances, allowances, mint/burn state, or transfer logic?
  • For each alias family, what are the separate answers to does this alias still reach the same balances?, does policy still mean the same protected asset after canonicalization?, and what helper authority should vanish once that answer is yes?
  • Where does the protocol currently equate different address with different asset, especially in sweepToken, rescue, adapter routing, collateral admission, or deny-list logic?
  • Can an alias address satisfy a non-underlying or unsupported asset check while still moving the same economic reserve the protected path was meant to exclude?
  • Are pause, freeze, quarantine, and listing controls attached per address or per canonical asset identity?
  • Do any helper functions accept arbitrary token addresses and then rely on address equality alone to decide whether the action is safe?
  • What exact behavior is shared across the canonical and alias surfaces: balanceOf, transfer, allowance consumption, mint/burn, or some narrower forwarding subset?
  • If the token has legacy migration or forwarding contracts, who can still activate them, and what prevents those surfaces from re-opening deauthorized reserve movement?
  • Can a bookkeeping or rescue helper mutate exchange-rate inputs, treasury balances, collateral accounting, or claimable assets elsewhere in the protocol if called through an alias?
  • How is the alias inventory maintained when a token upgrades, migrates, or adds compatibility entry points later?
  • What invariant proves that every protected asset policy remains true after canonicalization, even if the caller supplies any other known address for the same economic asset?

Lessons that should already be standard

  • Asset identity is broader than address identity. If one economic asset can answer through multiple addresses, policy keyed only by address is incomplete by definition.

  • Same balances, same protected asset, and same helper authority are three different review facts. Collapsing them is how teams end up saying the alias only changes naming right up until a rescue hook or adapter path moves live reserves.

  • Housekeeping helpers are not operational fluff when they can touch live reserves. sweepToken and rescue code often sit directly on the solvency boundary.

  • Legacy compatibility surfaces keep risk alive long after teams think an integration is finished. Migration shims deserve threat modeling, not just documentation.

  • Allowlists and blocklists should usually be per asset, not per token address, whenever aliasing is possible.

  • A token integration is not done when the preferred address works. It is done when every meaningful alternate entry surface is either canonicalized, constrained, or explicitly rejected.

  • Deprecation without deauthorization is a recurring failure shape. If an old token surface still reaches real balances, it is still part of the attack surface.

  • High-signal incidents:

    • [[../../../incidents/accounting-issuance-claims/compound-ctusd-legacy-tusd-double-entry-sweeptoken-exchange-rate-collapse-near-miss-2022-02-23|Compound cTUSD legacy-TUSD double-entry sweepToken() exchange-rate collapse near miss (2022-02-23)]] — the cleanest preserved exemplar: Compound blocked only the configured TUSD address in sweepToken(), but legacy TUSD forwarding address 0x8dd5... still controlled the same balances and let an attacker zero out totalCash economically.

Internal linkages

Control surface

  • The leverage sits in every place a protocol turns token address into a full statement about economic identity.

  • The recurring mistake is to treat different address as proof of different asset even when the token architecture deliberately preserved multiple entry points into one balance sheet.

  • The sharper control-surface split is which aliases still reach the same reserve, which policies are supposed to protect that reserve as one asset family, and which helper authorities only exist for truly other assets.

  • Once that happens, a policy exception written for other tokens can quietly inherit authority over the real underlying reserve.

  • Sources:

  • Last reviewed: 2026-07-26 UTC