Co-authored-by: Cursor <cursoragent@cursor.com>
8.5 KiB
Token Mapping and Mainnet Addresses (Chain 138 ↔ Ethereum Mainnet)
Last Updated: 2026-02-13
Status: Active
Source of truth: config/token-mapping.json
Overview
Ethereum Mainnet (chainId 1) in config/smart-contracts-master.json lists only CCIP relay contracts plus canonical WETH9 and LINK. It does not include wrapped/mirrored ERC‑20 addresses for tokens that originate on Chain 138 (e.g. Compliant USDT/USDC, WETH10). This document defines the full mapping and how to use it.
Definitive Mainnet Addresses (from source of truth)
| Token | Mainnet address | Notes |
|---|---|---|
| WETH9 (canonical) | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
Same on Chain 138; only token the current Mainnet CCIPRelayBridge accepts. |
| LINK (canonical) | 0x514910771AF9Ca656af840dff83E8264EcF986CA |
Canonical Mainnet LINK; relay bridge does not accept LINK yet (WETH9-only). |
For any other token (USDT, USDC, WETH10, etc.) the JSON and the Mainnet bridge do not specify a Mainnet “bridged” contract. Mainnet canonical references (for documentation only) are in config/token-mapping.json under mainnetCanonicalReference.
Full mapping table (Chain 138 → Mainnet)
| Token key | Chain 138 address | Mainnet address | Relay supported (138→Mainnet) |
|---|---|---|---|
| WETH9 | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
✅ Yes |
| LINK_Token | 0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03 |
0x514910771AF9Ca656af840dff83E8264EcF986CA |
❌ No (bridge WETH9-only) |
| WETH10 | 0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f |
— | ❌ No |
| Compliant_USDT | 0x93E66202A11B1772E55407B32B44e5Cd8eda7f22 |
— | ❌ No |
| Compliant_USDC | 0xf22258f57794CC8E06237084b353Ab30fFfa640b |
— | ❌ No |
| Tether_USDT_Chain138 | 0x15DF1D5BFDD8Aa4b380445D4e3E9B38d34283619 |
— | ❌ No |
“—” means no Mainnet wrapped/mirrored contract in the current design; the Mainnet CCIPRelayBridge has no token registry or factory for these.
Where mapping is used
- Relay service (
smom-dbis-138/services/relay):config.jsbuildstokenMapping(Chain 138 address → Mainnet address) fromconfig/token-mapping.jsonwhen available, otherwise uses a fallback object. Only WETH9 is accepted by the Mainnet bridge; LINK is mapped for future use. - Config:
config/token-mapping.jsonis the single source of truth.config/token-mapping-loader.cjsprovidesgetRelayTokenMapping()andgetTokenList()for consumers.
Mainnet bridge behaviour
- CCIPRelayBridge (Mainnet):
0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939- Accepts only WETH9 (
message.tokenAmounts[0].token == weth9). - No view functions such as
getWrappedToken(originChainId, originToken)ornativeToWrapped(...). - No on-chain token registry; no wrapped token deployment for Chain 138–origin tokens.
- Accepts only WETH9 (
- Getting Mainnet token address for a bridged token:
- WETH9: use
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2. - LINK: use
0x514910771AF9Ca656af840dff83E8264EcF986CA(canonical); relay bridge does not support it yet. - Anything else: not derivable from the current bridge or JSON; would require a different Mainnet contract that deploys/registers wrapped tokens and exposes a mapping.
- WETH9: use
Recommendations and suggestions
-
Keep
config/token-mapping.jsonas the single source of truth
Add or change token entries there; the relay and docs should reference it. When adding a new token with a Mainnet address, setmainnetAddressandrelaySupportedas appropriate. -
Extend Mainnet bridge for LINK (optional)
To support 138→Mainnet LINK via the relay, either:- Extend CCIPRelayBridge to accept LINK (and hold/fund LINK), or
- Deploy a separate receiver contract for LINK and point relay to it for LINK messages.
After that, setrelaySupported: truefor LINK intoken-mapping.json.
-
Document unsupported tokens
WETH10, Compliant_USDT, Compliant_USDC, and Tether_USDT_Chain138 have no Mainnet wrapped address in this design. For token lists or UIs, use this doc ortoken-mapping.jsonso integrators do not assume a Mainnet address exists. -
If you introduce wrapped tokens on Mainnet later
If a future bridge or TokenFactory deploys wrapped tokens on Mainnet for Chain 138 assets:- Add the Mainnet wrapped address to
config/token-mapping.jsonfor that token. - If the relay will deliver that token, add the Chain 138 → Mainnet mapping to the relay’s
tokenMapping(already driven bytoken-mapping.jsonwhen the config path is available). - Optionally add the wrapped contract to
config/smart-contracts-master.jsonunder chain 1 if you want it in the main contract list.
- Add the Mainnet wrapped address to
-
Canonical Mainnet references (reference only)
For documentation and off-chain tooling, canonical Mainnet addresses are inconfig/token-mapping.jsonundermainnetCanonicalReference(e.g. USDT, USDC, WETH9, LINK). These are not “bridged” addresses from Chain 138 unless explicitly mapped intokens. -
Relay service
When running the relay from the monorepo, ensureconfig/token-mapping.jsonandconfig/token-mapping-loader.cjsare available so the relay uses the full mapping. Fallback inconfig.jscovers WETH9 and LINK when the config is not present.
Additional recommendations
-
CI validation
The pipeline runsscripts/validation/validate-config-files.shwhenconfig/changes. That script checks forconfig/token-mapping.jsonand, if present, validates that it is valid JSON with a.tokensarray. Keep the file valid so CI passes. -
Sync when adding tokens
When adding a new token to Chain 138 (or a new bridged token), update both:config/smart-contracts-master.json(underchains.138.contractsif it is a contract),config/token-mapping.json(add an entry withkey,chain138Address,mainnetAddressif known,relaySupported,notes).
Optionally update CHAIN138_TOKEN_ADDRESSES.md and the cross-chain table there.
-
Runbook for LINK support
To enable 138→Mainnet LINK delivery, follow RELAY_BRIDGE_ADD_LINK_SUPPORT_RUNBOOK.md (extend bridge or deploy separate LINK receiver, then setrelaySupported: truefor LINK intoken-mapping.json). -
Token lists and UIs
When building token lists or UIs that show “Mainnet address” or “bridged address” for Chain 138 tokens, read fromconfig/token-mapping.jsonor this doc. Do not assume every Chain 138 token has a Mainnet address; only WETH9 is relay-supported today; LINK has a canonical Mainnet address but is not yet relay-supported.
Multi-chain mapping (138↔651940, 651940↔other chains)
For 138↔651940 and 651940↔56, 137, 100, 43114, 8453, 42161, 10, 25, 1, use config/token-mapping-multichain.json. The same loader provides:
getTokenMappingForPair(fromChainId, toChainId)— returns{ tokens, addressMapFromTo, addressMapToFrom }.getAllMultichainPairs()— list of defined chain pairs.getMappedAddress(fromChainId, toChainId, tokenAddress)— resolve token address on target chain.
See MAPPER_COVERAGE_BRIDGES_AND_LIQUIDITY_POOLS.md. To verify canonical token addresses per chain, use the explorer token lists in EXPLORER_TOKENS_CANONICAL_MAPPING.md.
References
- CCIP_BRIDGE_MAINNET_CONNECTION.md — Relay flow and mainnet contracts.
- RELAY_BRIDGE_ADD_LINK_SUPPORT_RUNBOOK.md — Optional runbook to add LINK support to the Mainnet relay bridge.
- MAPPER_COVERAGE_BRIDGES_AND_LIQUIDITY_POOLS.md — Mapper and multichain token mapping coverage.
- CHAIN138_TOKEN_ADDRESSES.md — Chain 138 token list.
config/token-mapping.json— 138↔Mainnet machine-readable mapping.config/token-mapping-multichain.json— 138↔651940 and 651940↔CCIP/canonical chains.config/token-mapping-loader.cjs— Loader API for relay and multichain tooling.- EXPLORER_TOKENS_CANONICAL_MAPPING.md — Explorer tokens/contracts list URLs for verifying canonical addresses per chain.