feat(tokenverifier)!: CCTPCodec via the chain accessor - #1450
jadepark-dev wants to merge 10 commits into
Conversation
huangzhen1997
left a comment
There was a problem hiding this comment.
You can probably also add the Solana localnets to verifier/pkg/token/cctp/consts.go
There was a problem hiding this comment.
🔵 Needs a closer look
An adapter-registration test gap and documentation inconsistency remain unresolved, warranting final human review.
Pull request overview
Refactors CCTP chain-specific behavior into injectable family adapters, enabling external Solana support while preserving EVM behavior.
Changes:
- Adds adapter registration and an EVM implementation.
- Routes attestation and message matching through adapters.
- Documents the breaking integration change.
File summaries
| File | Summary |
|---|---|
verifier/pkg/token/cctp/consts.go |
Restricts the domain catalog to EVM chains. |
verifier/pkg/token/cctp/attestation.go |
Uses adapters for attestation processing. |
verifier/pkg/token/cctp/attestation_solana_test.go |
Removes tests for externally provided Solana codecs. |
verifier/pkg/token/cctp/adapter.go |
Defines the adapter interface and registry. |
verifier/pkg/token/cctp/adapter_evm.go |
Implements and registers the EVM adapter. |
verifier/pkg/token/cctp/adapter_evm_test.go |
Tests adapter resolution and EVM codecs. |
go.mod |
Updates base58 dependency classification. |
changelog/2026-09-15_injectable_cctp_chain_adapters.md |
Documents migration and breaking behavior. |
Review details
Suppressed comments (2)
verifier/pkg/token/cctp/adapter_evm_test.go:23
- This test does not exercise the missing-registration branch it claims to cover: selector
1fails insideGetSelectorFamily, soAdapterFornever reaches the!oklookup atadapter.go:49-52. Use a known family without an adapter in this package (for examplechainsel.SOLANA_DEVNET) so regressions in the unregistered-family path are caught.
func TestAdapterForUnregisteredFamily(t *testing.T) {
// Selector 1 is in no chain-selectors family map, so no adapter can be resolved.
_, err := AdapterFor(protocol.ChainSelector(1))
require.Error(t, err)
verifier/pkg/token/cctp/consts.go:21
verifier/docs/token_verifier.md:150still says the full domain table is defined inconsts.go, but this change makesDomainsEVM-only and moves Solana domains into the family adapter. Update that documentation so non-EVM consumers are not directed to an incomplete catalog.
// Solana selectors are absent: the Solana adapter owns that table.
- Files reviewed: 8/8 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| // ChainCodec holds the chain-family-specific CCTP knowledge the verifier needs: the | ||
| // Circle domain of a source chain, and the codecs for that chain's native transaction | ||
| // hash and address encodings. | ||
| // | ||
| // One codec exists per chain family. The EVM codec lives in this package; other families | ||
| // register theirs from their own module. The verifier resolves the codec from the source | ||
| // chain's family, so the core path holds no chain-specific branch. | ||
| type ChainCodec interface { |
There was a problem hiding this comment.
I feel like this should be defined in pkg/chainaccess and added to the Accessor interface, since that is the standard registration pattern already defined in the protocol module for chain-specific deps.
type Accessor interface {
// already defined things ...
CCTPCodec() CCTPCodec
}There was a problem hiding this comment.
Hmm I thought about this, felt like mixing layers into Accessor.. but yeah probably it's better than scattering them out
|
|
||
| ## Migration Guide | ||
|
|
||
| Do nothing for an EVM-only token verifier. |
There was a problem hiding this comment.
Ideally we dogfood it for EVM as well - lets not have it be a special case. I believe if you go the accessor path, it'll be a standard case like Solana.
|
Code coverage report:
Files added (in
|
Description
The CCTP token verifier held its chain knowledge in
verifier/pkg/token/cctp: a staticDomainsmap, plusencodeTxHashanddecodeAddressbranching on the chain family. A source chain with noDomainsentry failed atFetchwithunsupported source chain selector, before the attestation API call, so the local devenv Solana chain never attested and the indexer returned 404.This change moves that knowledge to the chain accessor.
chainaccess.CCTPCodecis a new interface inpkg/chainaccesswith three methods:Domain,EncodeTxHash, andDecodeAddress.Accessorexposes it throughCCTPCodec(), the same way it exposesSourceReader().cmd/verifier/tokenfactory.gobuilds amap[protocol.ChainSelector]chainaccess.CCTPCodecfrom the accessors it already resolves, andFetchreads that map.cctp.Domainskeeps only the EVM entries; each chain repository owns its own table, and the Solana table lives in the paired chainlink-ccip-solana PR.Breaking:
cctp.NewAttestationServicetakes the codec map as a new required argument; a source chain whose accessor does not implementCCTPCodecnow fails atFetchwithno CCTP chain codec for source chain selectorinstead of failing at startup; an EVM-only verifier is unchanged. Seechangelog/2026-09-15_injectable_cctp_chain_codecs.md.Testing
go test ./pkg/chainaccess/... ./integration/pkg/accessors/evm/... ./verifier/pkg/token/cctp/... ./cmd/verifier/...passes.integration/pkg/accessors/evm/codec_test.gocovers the EVM codec, andattestation_test.gocovers the codec path.go build ./...andgolangci-lintare clean. The paired chainlink-ccip-solana caseTestSolana2EVM/TokenTransfer/CCTPpasses on a local devenv with this change.Checklist
changelogdirectory)