Repository navigation
feat(chains): default to the v2.12 Portal and provers (ECO-2403) - #33
Conversation
Point every production chain's Portal/prover default at the eco-routes v2.12 generation that the solvers switch to in eco/eco-solver#1272: Portal 0xEC000769..., HyperProver 0xEC08fb46... (replacing the removed LayerZero prover on Ethereum/Optimism/Base/Arbitrum/Polygon), the Base Tron-corridor PolymerProver 0xEC0DeD08..., Arc on the shared addresses, and the Tron Portal/PolymerProver pair TDYD42Vm.../TU42qLG4.... Drop BNB Smart Chain, Sonic, Celo and Ink and their token entries: no v2.12 deployment exists there, so nothing can fill an intent on them. Testnets and the Anvil fork E2E (pinned to a pre-v2.12 fork block) keep their existing addresses. Claude-Session: https://claude.ai/code/session_01PVso5BBb8ZQGg6jBtTh4MG
OverviewThis PR updates the default Portal and Prover addresses across all production chains to the eco-routes v2.12 generation and removes chains (BNB Smart Chain, Sonic, Celo, Ink) that lack a v2.12 deployment. The QA agent verified that comprehensive test coverage was added, including a new pinning test suite for the v2.12 addresses and explicit assertions for the removed chains. The review team identified no issues or regression risks. QA & Test CoverageNo issues found in this domain. Web SecuritySkipped: not applicable to this PR — PR updates blockchain contract addresses and configuration; no web security concerns. Blockchain SecurityNo issues found in this domain. PerformanceSkipped: not applicable to this PR — PR is a configuration update with no performance implications; no algorithmic or computational changes. Stats
Automated review by Eco's specialized review team. Architecture, business logic, and correctness remain with the human reviewer. |
Summary
routes-cli builds intents that the production/staging solvers fill, so its per-chain Portal/prover defaults have to be on the generation the solvers run. eco-routes v2.12 (proven cancellation, ECO-2403) deployed under a new root SALT, and eco/eco-solver#1272 moves every solver deployment to it. This PR moves routes-cli's production defaults to v2.12 and drops the chains that have no v2.12 deployment (the same set the solver drops in its runbook §10.3).
This is an intent builder change: it replaces the old addresses and does not keep them alongside.
Merge order: merge only after every solver deployment this service targets has switched to v2.12 (eco/eco-solver#1272 §10.1). A solver can't fill an intent on the other generation.
Where these defaults are used
The normal publish path takes the source Portal, the prover and the destination Portal from the Eco API quote, so a quoted publish follows whatever generation the quoting solver serves.
chains.config.tsis used for the manual fallback (quote fails →route.portal= the destination chain's configured Portal, prover auto-selected from the configuredprovers),--prover-type <name>, the portal prompt default,EvmPublisherwhen no Portal is passed, and thestatus/watch lookup when no quote is present. After the switch, the old defaults would publish unfillable intents through every one of those paths.The 0x399D… "prod portal" decision
Ethereum, Optimism, Base, Arbitrum and Polygon had
0x399Dbd5D…labelled "prod portal", paired with LayerZero prover0x0C4E3063…. They came in with #17 (LZ prover support). On eco-solvermainthat address appears only inhelm/eco-solver/config/ephemeral.yaml(routes-ts 3.2 / ephemeral). The production and staging helm files use the fleet Portal0xEC000064…. So the "prod" default already pointed at a Portal the production fleet doesn't serve, and it only worked through the quote path. On the #1272 branch every deployment, ephemeral included, goes to0xEC000769…, so there's nothing left to target the old address. All five chains move to the v2.12 Portal. LayerZero is gone in v2.12, so each chain's prover default becomes the v2.12 HyperProver. With one common type (Hyperlane) between any two EVM chains, auto-selection in the manual fallback still works without a prompt.What changed
src/blockchain/chains.config.ts:V2_12_PORTAL/V2_12_HYPER_PROVERconstants (one CREATE3 address on every v2.12 EVM chain).0x399D…→0xEC000769…, proverLayerZero 0x0C4E…→Hyperlane 0xEC08fb46….0xE3e4e6F2…→0xEC0DeD08…. Polymer stays listed on Base only, the Tron-corridor endpoint, for the single-common-prover reason in the comment.0xEC002CA1…→0xEC000769…, HyperProver0xec004Ab4…→0xEC08fb46….TT6jKgnB…→TDYD42Vm…, PolymerTLvVHqZZ…→TU42qLG4…, still paired.src/config/tokens.config.ts: removed the token entries for the four dropped chains (USDC on Sonic/Celo, USDT on Celo, USDT0/USDG on Ink) and the BSC-onlybUSDC/bUSDTsymbols.tests/blockchain/v2-12-mainnet-config.test.ts(new): pins the v2.12 Portal/provers per production chain and asserts that no production chain carries a pre-v2.12 Portal/prover or a LayerZero prover.tests/blockchain/arc-mainnet-config.test.ts: Arc now pins the shared v2.12 Portal/HyperProver.tests/blockchain/chains.config.test.ts,tests/config/tokens.config.test.ts,tests/cli/token-resolver.service.test.ts: dropped the Celo/Ink cases and added assertions that the four removed chains have no chain or token entry.tests/quote/quote.service.test.ts,tests/quote/gateway-quote.adapter.test.ts: quote-response fixtures moved to the v2.12 Portal/HyperProver. The adapter test's destination Portal keeps a different address on purpose, so the test can still telltx.toapart fromroute.portal.tests/blockchain/evm-publisher.integration.test.ts,tests/integration/intent-publishing.test.ts,tests/integration/publish-non-interactive.test.ts: mocked Portal fixture0x399D…→ v2.12.tests/e2e/setup/anvil-helpers.ts: kept0x399D…and added a comment. CI forks Base atFORK_BLOCK_NUMBER: 28000000, which predates the v2.12 Portal, so the address and the fork block have to move together.ARCHITECTURE.md: updated the production chain and token tables..changeset/v2-12-portal-defaults.md: minor bump (user-facing default change plus removed chains).Solana / Tron instruction compatibility
fundinstruction itself (plus an unusedpublishbuilder), from its vendored gen-1 IDL (src/commons/idls/portal.idl.ts). I diffed it against the gen-2 IDL vendored on the solver branch (src/modules/blockchain/svm/targets/idl/portal-v2.idl.ts).fundhas the same discriminator, the same 7 accounts in the same order and identicalFundArgs/Reward/TokenAmount/Bytes32types. The only difference is that gen-2 markspayerwritable. routes-cli always passes the same key aspayerandfunder, andfunderis writable, so the compiled message is unchanged.publish,PublishArgs,Routeand theIntentPublished/IntentFundedevents are identical, and the vault PDA seed ("vault"+ intent hash) is unchanged. The Solana program id comes from the quote or--portal-address, never from this config, so nothing is swapped under a gen-1 encoder. routes-cli doesn't buildrefundorclose_fulfill_marker, the two instructions whose layout gen-2 changed. If someone later adds a separate fee payer, the vendored IDL'sfund.payerneedswritable: true.publishAndFund, via the EVM Portal ABI, including on Tron. The solver branch's v2.12 Portal ABI diff is additive only (cancellation), sopublishAndFundis unchanged.Validation
pnpm -C <worktree> install --frozen-lockfile: okpnpm typecheck: exit 0pnpm lint: 0 errors. The 30 warnings were already there before this change (no-unsafe-assignmentin existing tests).pnpm format:check: all files passpnpm test: 23 suites, 230 tests passed. That's the whole jest suite, sincejest.config.tsexcludestests/e2e/.pnpm test:e2e(Anvil Base fork, needs live infra). Its Portal fixture is deliberately unchanged, see above.Addresses verified on-chain 2026-09-29
0xEC000769A73b70e16f361a442292500b3BCf4A85:version()="2.12.0"on Ethereum, Optimism, Base, Arbitrum and Polygon (public RPCs).0xEC08fb4647f3f50d1162a578d481266687C60fc5:PORTAL()=0xEC000769…on the same five chains.0xEC0DeD087Ee6C55991Bb4D4567ca1134c5353Ed6:PORTAL()=0xEC000769…on Base.TDYD42VmbScmqYkqG97aLgRN74Dqq9Fuva(hex0x27262594c6088865ac3e7ac20f401af3bd379b1b):version()="2.12.0". PolymerProverTU42qLG4ixTZ56jYFVAke32DmTcEkiU4zv:PORTAL()=0x27262594…(TronGrid).Owed / not in this PR
README.mddocumentsPORTAL_ADDRESS_ETH/_BASE/_OPTIMISM/_SOLANAoverrides that no source reads (already stale, left as is).Related: eco/eco-solver#1272
https://claude.ai/code/session_01PVso5BBb8ZQGg6jBtTh4MG