Skip to content

feat(statics): ERC-7984 statics registry for wrapper↔underlying pairs - #9459

Draft
bitgo-ai-agent-dev[bot] wants to merge 3 commits into
masterfrom
chalo-1156-erc7984-statics-registry
Draft

feat(statics): ERC-7984 statics registry for wrapper↔underlying pairs#9459
bitgo-ai-agent-dev[bot] wants to merge 3 commits into
masterfrom
chalo-1156-erc7984-statics-registry

Conversation

@bitgo-ai-agent-dev

Copy link
Copy Markdown
Contributor

What

  • Add modules/statics/src/erc7984Registry.ts — a new per-network static registry for ERC-7984 (Zama fhEVM) confidential token wrapper↔underlying ERC-20 pairs
  • Each entry records wrapperAddress, underlyingErc20Address, rate (bigint, ≥ 1), requiresApprovalReset (USDT-pattern flag), isVetted, and isActive
  • Wire Hoodi testnet pairs (hteth:ctest1, hteth:cusdt) and six Ethereum mainnet pairs (eth:czama, eth:cxaut, eth:ctgbp, eth:cweth, eth:cusdt, eth:cusdc)
  • Export getWrapperPair(networkName, wrapperAddress) and getActiveWrapperPairs(networkName) helpers for calldata builders that need the underlying address or approval-reset semantics at tx-build time
  • All three levels of the registry (top-level object, per-network arrays, pair objects) are Object.freeze()-d; Erc7984WrapperPair fields are all readonly; return types use ReadonlyArray
  • Module-load-time validateRegistry() throws on bad address format, rate < 1n, or duplicate wrapper addresses within a network
  • getWrapperPair guards against null/undefined/empty wrapperAddress without crashing; address lookup is case-insensitive
  • Export everything from modules/statics/src/index.ts
  • Unit tests in modules/statics/test/unit/erc7984Registry.ts covering: shape invariants, uniqueness, immutability, case-insensitive lookup, happy-path lookups for Hoodi + mainnet, null/empty address guards, unknown-network fallbacks, and filter-exclusion for isVetted=false/isActive=false pairs

Why

  • CHALO-1135 (ERC-7984 shield/unshield calldata builders) requires a per-network registry of wrapper↔underlying pairs with approval-reset semantics so that buildApproveCalldata, buildWrapCalldata, and buildUnwrapCalldata can look up the correct underlying ERC-20 address and know whether to reset the USDT allowance to 0 before approving a new amount
  • This registry is a blocking dependency for CHALO-1153 (buildApproveCalldata), CHALO-1154 (buildWrapCalldata), CHALO-1155 (buildUnwrapCalldata), CHALO-1157 (buildFinalizeUnwrapCalldata), and CHALO-1160 (unit tests for builders)

Test plan

  • modules/statics unit tests pass: yarn unit-test --scope @bitgo/statics (the pre-existing coins.ts failure due to missing @bitgo/sdk-core compiled artifacts in CI is unrelated to this diff and exists on master)
  • TypeScript type-check passes: cd modules/statics && npx tsc --noEmit
  • Verify getWrapperPair returns correct pair for hteth:cusdt with mixed-case address input
  • Verify getActiveWrapperPairs returns 2 Hoodi pairs and 6 mainnet pairs
  • Verify that mutating a returned pair throws in strict mode (frozen object)

Ticket: CHALO-1156

…airs

Introduce erc7984Registry.ts in @bitgo/statics with per-network static
configuration for ERC-7984 confidential wrapper↔underlying ERC-20 pairs.

Each entry records:
  - wrapperAddress / underlyingErc20Address (checksummed-lowercase hex)
  - rate (underlying base units per wrapper base unit, bigint ≥ 1)
  - requiresApprovalReset (USDT-pattern ERC-20s that need a 0-allowance reset)
  - isVetted / isActive (gating flags for live shield/unshield eligibility)

Wire Hoodi testnet pairs (hteth:ctest1, hteth:cusdt) and all six Ethereum
mainnet pairs (eth:czama, eth:cxaut, eth:ctgbp, eth:cweth, eth:cusdt,
eth:cusdc).  Export getWrapperPair() and getActiveWrapperPairs() helpers
for calldata builders that need the underlying address or approval-reset
semantics at tx-build time.

Unit tests cover: shape invariants, uniqueness within network, case-
insensitive address lookup, happy-path lookups for Hoodi and mainnet,
and unknown-network/unknown-address fallbacks.

Ticket: CHALO-1156
Session-Id: 4d410361-d10d-4cbb-b8fa-1a76aad1adcc
Task-Id: 0df7e500-dcfa-4bdc-83de-b3a56aa5dd09
Address review findings from post-commit review agents:

- Freeze the registry object, per-network arrays, and pair objects with
  Object.freeze() so callers cannot corrupt the module-level singleton.
- Add readonly modifiers to all Erc7984WrapperPair interface fields and
  tighten Erc7984Registry / getActiveWrapperPairs return types to use
  ReadonlyArray so TypeScript propagates immutability to callers.
- Add a module-load-time validateRegistry() IIFE that throws on invalid
  wrapperAddress/underlyingErc20Address format, rate < 1n, or duplicate
  wrapper addresses within a network — catches bad entries before any
  caller sees them.
- Guard getWrapperPair against null/undefined/empty wrapperAddress so
  JS callers cannot trigger a TypeError from .toLowerCase() on a falsy value.
- Normalize both sides of the address comparison (p.wrapperAddress is
  already lowercase in the registry, lower is the lowercased input) so
  future mixed-case entries still resolve correctly.
- Expand unit tests: immutability assertion, null wrapperAddress guard,
  empty wrapperAddress guard, and two explicit filter-exclusion tests
  (isVetted=false excluded, isActive=false excluded) to cover the filter
  predicate that was previously exercised only on all-true data.

Ticket: CHALO-1156
Session-Id: 4d410361-d10d-4cbb-b8fa-1a76aad1adcc
Task-Id: 0df7e500-dcfa-4bdc-83de-b3a56aa5dd09
@linear-code

linear-code Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

CHALO-1156

@ralph-bitgo
ralph-bitgo Bot force-pushed the chalo-1156-erc7984-statics-registry branch from 846cf0e to a22afb7 Compare August 10, 2026 09:13
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the chalo-1156-erc7984-statics-registry branch from a22afb7 to b4f29f6 Compare August 10, 2026 09:13
Prettier check was failing in CI because two files had lines
exceeding the project's print-width limit. Auto-fixed by running
`yarn fmt` in modules/statics — no logic changes.

Ticket: CHALO-1156
Session-Id: d928878d-20db-4ab7-bbef-bfda0854f79c
Task-Id: f43b12b1-fbfc-411d-9c9a-83b869fb7df3
@ralph-bitgo
ralph-bitgo Bot force-pushed the chalo-1156-erc7984-statics-registry branch from 3b1ea6b to ec9d0f0 Compare August 10, 2026 11:43
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the chalo-1156-erc7984-statics-registry branch from ec9d0f0 to 8667104 Compare August 10, 2026 11:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant