Skip to content

feat(contract_manager): migrate tooling for MigrateGovernanceAndWormhole - #3939

Open
keyvankhademi wants to merge 4 commits into
feat/xc-admin-set-wormhole-and-datasourcesfrom
feat/contract-manager-evm-pro-migrate
Open

feat(contract_manager): migrate tooling for MigrateGovernanceAndWormhole#3939
keyvankhademi wants to merge 4 commits into
feat/xc-admin-set-wormhole-and-datasourcesfrom
feat/contract-manager-evm-pro-migrate

Conversation

@keyvankhademi

@keyvankhademi keyvankhademi commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds migrate_evm_pricefeed_to_pro.ts to deploy/reuse pro wormhole + new Pyth impl, then propose [UpgradeContract, MigrateGovernanceAndWormhole] for legacy proxies.
  • EvmChain.generateGovernanceMigrateGovernanceAndWormholePayload(...) wraps the xc_admin codec (wormhole, data sources, new governance emitter, index).
  • Requires explicit --governance-emitter-chain, --governance-emitter-address, --governance-data-source-index (does not silently reuse legacy governance).
  • check_proposal.ts verifies migrate targets including governance fields.
  • Assumes fee already set to 0 via existing SetFee before migrate.

Depends on sibling PRs:

  • EVM Solidity handler (MigrateGovernanceAndWormhole)
  • xc_admin_common codec export

Test plan

  • Typecheck/build after xc_admin codec PR is available
  • Dry-run migrate script help / required governance flags
  • check_proposal against a sample proposal with action 10
  • Confirm usage docs mention SetFee-before-migrate and post-cutover governance switch

Add SetWormholeAddressAndDataSources payload helper, migrate script, and
proposal verification for upgrading legacy proxies onto pro-compatible
wormhole + data sources without changing the consumer address.
Copilot AI review requested due to automatic review settings July 28, 2026 20:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
api-reference Error Error Jul 30, 2026 8:40pm
component-library Ready Ready Preview Jul 30, 2026 8:40pm
developer-hub Error Error Jul 30, 2026 8:40pm
4 Skipped Deployments
Project Deployment Actions Updated (UTC)
entropy-explorer Skipped Skipped Jul 30, 2026 8:40pm
insights Skipped Skipped Jul 30, 2026 8:40pm
proposals Skipped Skipped Jul 30, 2026 8:40pm
staking Skipped Skipped Jul 30, 2026 8:40pm

Request Review

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 4 potential issues.

Open in Devin Review

Comment on lines +158 to +163
const matchesProduction =
JSON.stringify(action.dataSources) ===
JSON.stringify(proProductionSources);
const matchesStaging =
JSON.stringify(action.dataSources) ===
JSON.stringify(proStagingSources);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Migration proposal check always warns that data sources are wrong

The proposal's data sources are compared to the expected pro data sources by turning both into text and matching character-for-character (JSON.stringify(action.dataSources) === JSON.stringify(proProductionSources) at contract_manager/scripts/check_proposal.ts:158-163), so a correct proposal is still flagged as not matching.
Impact: Operators verifying a mainnet migration proposal will always see "data sources do not match" even when the proposal is correct, defeating the check.

Key-order mismatch between decoded payload and expected config

The decoded action's data sources are produced by the DataSourceLayout struct which lists fields in the order emitterChain then emitterAddress (see governance/xc_admin/packages/xc_admin_common/src/governance_payload/SetDataSources.ts:13-17), so each object serializes as {"emitterChain":26,"emitterAddress":"..."}.

The expected sources from getDefaultDeploymentConfig declare the fields in the opposite order — emitterAddress first, then emitterChain (contract_manager/src/core/base.ts:154-169, 246-253) — so they serialize as {"emitterAddress":"...","emitterChain":26}.

JSON.stringify preserves insertion order, so the two strings never match even when the data is identical, making both matchesProduction and matchesStaging always false and always taking the WARNING branch at check_proposal.ts:168-175.

Suggested change
const matchesProduction =
JSON.stringify(action.dataSources) ===
JSON.stringify(proProductionSources);
const matchesStaging =
JSON.stringify(action.dataSources) ===
JSON.stringify(proStagingSources);
const normalizeSources = (
sources: { emitterChain: number; emitterAddress: string }[],
) =>
JSON.stringify(
[...sources]
.map((s) => ({
emitterChain: s.emitterChain,
emitterAddress: s.emitterAddress
.replace(/^0x/i, "")
.toLowerCase(),
}))
.sort((a, b) =>
`${a.emitterChain}:${a.emitterAddress}`.localeCompare(
`${b.emitterChain}:${b.emitterAddress}`,
),
),
);
const matchesProduction =
normalizeSources(action.dataSources) ===
normalizeSources(proProductionSources);
const matchesStaging =
normalizeSources(action.dataSources) ===
normalizeSources(proStagingSources);
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +174 to +181
payloads.push(
chain.generateGovernanceSetWormholeAddressAndDataSourcesPayload(
proWormhole.address.replace("0x", ""),
proDataSources,
0n,
0n,
),
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Migrate script depends on codec not present in this branch

migrate_evm_pricefeed_to_pro.ts and check_proposal.ts both import SetWormholeAddressAndDataSources from @pythnetwork/xc-admin-common, but that codec does not exist in this branch (confirmed no matches under governance/). The PR description states it is stacked on the xc_admin codec PR. Until that merges, this code will not build/typecheck. Worth confirming the retarget/merge order noted in the description before merging.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +148 to +152
if (action.newFeeValue !== 0n || action.newFeeExpo !== 0n) {
console.log(
` WARNING: expected fee 0/0 for pro migrate, got ${action.newFeeValue}/${action.newFeeExpo}`,
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Fee comparison assumes bigint decode type

check_proposal.ts:148 compares action.newFeeValue !== 0n / action.newFeeExpo !== 0n (bigint literals). If the not-yet-present codec decodes these fee fields as JS number rather than bigint, these strict comparisons would always be true (number !== bigint), producing a spurious fee warning. Confirm the codec decodes fee value/expo as bigint to match the u64be usage assumed here and the 0n/0n args passed in the migrate script (migrate_evm_pricefeed_to_pro.ts:178-179).

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +106 to +108
const isMainnet = selectedChains[0]?.isMainnet() ?? false;
const vault =
DefaultStore.vaults[isMainnet ? MAINNET_VAULT_ID : DEVNET_VAULT_ID];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Testnet migration routes proposal through devnet vault

Unlike upgrade_evm_pricefeed_contracts.ts which always uses the mainnet-beta vault, migrate_evm_pricefeed_to_pro.ts:106-108 selects DEVNET_VAULT_ID when the selected chains are testnet. Worth confirming that testnet EVM governance is actually proposed through the devnet Squads vault (devnet_6baWtW1zTUVMSJHJQVxDUXWzqrQeYBr6mu31j3bTKwY3) and that this key exists in DefaultStore.vaults; if the vault key is wrong, vault is undefined and the non-dry-run path silently does nothing (optional chaining) rather than erroring.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Keep the migrate tooling PR scoped to code changes only.
Assumes fee was already set to 0 via SetFee before migrate.
…ceAndWormhole

Expand action 10 payloads with explicit governance emitter and index CLI args.
@vercel
vercel Bot temporarily deployed to Preview – staking July 30, 2026 20:37 Inactive
@vercel
vercel Bot temporarily deployed to Preview – insights July 30, 2026 20:37 Inactive
@vercel
vercel Bot temporarily deployed to Preview – entropy-explorer July 30, 2026 20:37 Inactive
@vercel
vercel Bot temporarily deployed to Preview – proposals July 30, 2026 20:37 Inactive
@keyvankhademi keyvankhademi changed the title feat(contract_manager): EVM legacy→pro in-place migrate tooling feat(contract_manager): migrate tooling for MigrateGovernanceAndWormhole Jul 30, 2026
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.

2 participants