on bridged token resolution

July 29, 2025

It's not a very interesting topic, but the very slight intricacies of remote token resolution in bridging protocols is something I've noticed and crafted opinions on over the last few months.

The implications can be serious, resulting in essentially burned or hard to rescue assets to the value of millions of dollars (example 1, example 2, example 3). But there's no one size fits all solution, which explains the different approaches we'll look at here.

Let's get into it. Exceptions aside, initiating a token bridge usually looks like one of the following function calls,

function bridgeAsset(
  address localToken,
  address remoteToken,
  uint256 amount
) external;

Where the bridge being called has little to no concept of the remote token, but it might know about the destination implicitly - ie the native bridge for a rollup.

function bridgeAsset(
  uint256 destinationChainId,
  uint256 amount
) external;

Where the bridge contract is specific to some asset and remote chain IDs are registered on each spoke of the bridge configuration - common for token interoperability solutions like LayerZero OFTs or Hyperlane HWRs.

It's difficult to generalise these so broadly but the implication is that either the bridge contract knows about the remote asset being bridged (ie, was registered first), or it doesn't.

A few examples should help make this more clear, broadly broken down by the two aforementioned examples.

Native bridge contracts

With most popular rollup bridges - the bridge is specific to the rollup in question. The OP Mainnet bridge contract address is different to the one for Base which is different to Arbitrum, and messaging is bidirectional. So the bridge contract on Ethereum knows the rollup is the destination and the reverse holds true, the bridge contract on the rollup knows Ethereum is the destination chain.

So a destinationChainId (or similar) parameter doesn't need to be specified.

OP Stack native bridge

Initiating an OP Stack deposit allows specifying any combination of local and remote tokens, so what happens if those parameters are passed incorrectly?

op-stack

Maybe I try to encode the local address as USDC on Ethereum, and the remote address as USDC on Base? Or what if I specify a different token address?

Those tokens are essentially lost! They can be recovered if the rollup team does a bridge contract upgrade on Ethereum to rescue them, but with so much at stake for these rollup teams (in some cases billions of dollars) we see that rarely happen.

To drill into these examples a little further.

USDC on Ethereum to USDC on Base

What happens here is that the tokens will be locked up on Ethereum, but when the standard bridge goes to mint/unlock these tokens on the rollup, it won't be able to! The L2StandardBridge doesn't having minting rights over USDC, and there's unlikely to be any USDC held by the rollup contract to release.

Token A on Ethereum to Token B (not A.b) on Base

A similar case can happen when a token is correctly deployed on a rollup, and wired up to the corresponding token on Ethereum. But someone tries to bridge into another asset. Here the same thing happens, the asset is locked up on Ethereum but never minted/unlocked on the rollup, essentially lost forever!

Takeaways

With these cases in mind, we refer to token resolution as being done offchain. Frontends and applications need to check the local / remote token connection is valid. Which isn't always easily done when the remote token disables withdrawals! A registry can be helpful here, like ethereum-optimism.github.io which attempts to define tokens and their bridge contracts.

Arbitrum Nitro native bridge

Arbitrum Orbit rollup operates via a dual GatewayRouter / Gateway architecture. As the name suggests, the GatewayRouter handles calling the correct Gateway for a given token, and tokens always correspond to a particular Router, although a Router can handle many different tokens. A fallback default Gateway is used if no custom Gateway for a token has been set.

As such, only the local token address needs to be specified when bridging.

orbit-1

On the rollup side, the GatewayRouter checks if the corresponding the rollup token address for the bridged token has already been deployed (via a deterministic salted deployment). If not, the Gateway handles deploying that token to the well known address. This is pretty sweet, because comparing with the examples we explored earlier, it could never happen that a user bridges assets to a contract that doesn't exist. In the worst case a new token would be deployed, and the user would be able to bridge out (observing the lengthy withdrawal period).

orbit-2

For cases where more functionality is required of the rollup token, custom gateways can be registered for a token via a DAO vote. More on this later on.

Other rollups

Taiko

Taiko operates in a very similar manner to Arbitrum Orbit rollups, without the gateway overhead. When canonical tokens are bridged a standard ERC20 token is deployed on the other side. Overrides to this are permissioned and can be done via changeBridgedToken, which starts a migration process so users can exit from the old token.

All the relevant code for this can be found in the ERC20Vault.

Linea

For the purposes of this post, Linea token bridging is essentially the same as Taiko and we won't cover it.

However it's important to note that no migration functionality exists, tokens need to be reserved ahead of time.

Interop solutions

Coming to another bridging mechanism, let's explore interoperability solutions, or where the bridge contract is often specific to the asset in question, and where no addresses need to be specified when bridging.

The two examples we'll explore here are Hyperlane HWR's and LayerZero OFTs, although the assumptions hold true for many other protocols like Chainlinks CCIP.

Interestingly, Wormhole provides this functionality via their NTT framework while also offering the functionality already explored in this post via their token bridge.

With both these protocols in the context of bridging an already deployed token, a wrapping contract is deployed that handles locking up the assets. On the remote chain, assets are minted.

HWR bridging requires specifying the destinationChainId,

hyperlane

OFT bridging requires an endpointId, but in essence it is the same,

hyperlane

When bridging these assets, a remote router (for HWR's) or peer (for OFTs) needs to have been previously registered on the source chain. Bridging to a remote chain that isn't registered will simply revert.

This is clean, but doesn't totally stop asset loss. Remote peers or routers can still be unenrolled or degistered on one side without the other knowing about it, leading to tricky situations where asset issuers often need to jump in and help out.

Takeaways

So what are the takeaways here? There's seemingly a lot of variation in these configurations for reasonably similar outcomes.

Offchain token resolution is a great and somewhat necessary end state for rollups, where permissionless token deployment and bridging is desireable. With many of the rollups outlined nothing there's nothing to stop someone deploying a token, bridging it over and using it. Indeed we see entire platforms (like Supermigrate) built around this.

The OP Stack intricacy, where a remote token address is specified, seems to exist out of simplicity. The OptimismMintableERC20Factory exists as a helper for deploying correctly wired up tokens, but it still requires users to know about in advance. Because the OP Stack bridging mechanism is so simple, it's also possible to deploy StandardBridge-like contracts on top of the CrossDomainMessenger, like Lido have done with their wstETH and stETH tokens.

Interoperability providers are for now focused on asset issuers, where control of the bridging and the available chains are locked down by the team. But I wouldn't be surprised to see a rollup or chain come online that explicitly endorses a particular interoperability protocol and discourages tokens bridged via other means.