# \[PASSED\] OP-PIP-132: Pyth Core Deprecation (EVM)

**URL:** <https://forum.pyth.network/t/passed-op-pip-132-pyth-core-deprecation-evm/2672>\
**Category:** Proposals\
**Tags:** operational-pip\
**Created:** [August 25, 2026, 5:30pm UTC](https://forum.pyth.network/t/passed-op-pip-132-pyth-core-deprecation-evm/2672 "2026-08-25T17:30:49Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![KemarTiti](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.pyth.network/kemartiti/32/5_2.png) [@KemarTiti](https://forum.pyth.network/u/KemarTiti)\
**Post date:** [August 25, 2026, 5:30pm UTC](https://forum.pyth.network/t/passed-op-pip-132-pyth-core-deprecation-evm/2672/1 "2026-08-25T17:30:50Z")

</div>

## Abstract

Repoint Pyth Core on 33 EVM deployments (19 mainnet, 14 testnet) at the upgraded Pyth Core data source and at a Wormhole contract carrying the Pyth Pro guardian set, as the on-chain half of the [Pyth Core upgrade](https://www.pyth.network/blog/the-pyth-core-upgrade) scheduled for **26 August 2026, 16:00 UTC**.

This [proposal](https://proposals.pyth.network/?tab=proposals&proposal=9yuPH43L5ouV4qBKEaZV8TYavZ3TLtePzaEJb4SKWgje) executes three governance actions per chain, in this order:

1. **UpgradeContract → new Pyth Core implementation** (action `0`) — replaces the dual-verification rule in `SetWormholeAddress`, which structurally prevents moving a Pyth Core contract to a Wormhole contract with a _different_ guardian set.
2. **SetDataSources → upgraded Pyth Core data source** (action `2`) — replaces the three legacy Pythnet/Solana data sources with the single upgraded Pyth Core data source.
3. **SetWormholeAddress → new Wormhole receiver** (action `6`) — repoints the contract at a freshly deployed Wormhole receiver holding the Pyth Pro guardian set.

99 instructions in total (33 chains × 3 actions).

Protocol fees on EVM were already zeroed by [OP-PIP-128](https://forum.pyth.network/t/passed-op-pip-128-pyth-core-sunset-fee-zeroing-balance-repatriation/2662) and [OP-PIP-130](https://forum.pyth.network/t/passed-op-pip-130-pyth-core-additional-contract-upgrades-and-fee-balance-repatriation/2669). This proposal contains no `SetFee` and no `WithdrawFee` action.

## Rationale

Under the Pyth Core to Pyth Pro Migration ([OP-PIP-100](https://forum.pyth.network/t/passed-op-pip-100-pyth-core-to-pyth-pro-migration/2420)), Pythnet is sunsetting and Pyth Core price updates move to the Pyth Pro publishing stack. On EVM the change has two on-chain parts: which emitter the contract accepts price updates from (the _data source_), and which guardian set signs the VAAs carrying those updates (the _Wormhole contract_).

Today every Pyth Core contract points at a Wormhole receiver holding **Wormhole guardian set 7 (19 guardians)**. Pyth Pro publishes through a 5-key Pyth multisig, so each contract has to be repointed at a Wormhole receiver holding that set.

`SetWormholeAddress` (action `6`) has existed since the contract was written, but its old implementation made this specific move impossible. It set the new Wormhole address and then re-verified _the same governance VAA_ through the new contract.

That check is a sanity guard against bricking the contract on a bad address, and it holds only when the old and new Wormhole contracts share a guardian set. The governance VAA here is signed by the Wormhole guardians, so re-verifying it against a receiver holding the Pyth Pro guardian set always fails and the instruction always reverts. Upgrading the implementation is therefore a hard prerequisite, not a convenience.

The replacement keeps a weaker but sufficient guard — the new address must be non-zero and must have code ([commit `4739bbc`](https://github.com/pyth-network/pyth-crosschain/commit/4739bbcb8f091ec1126deee40bf00f27df8b28f9)).

The same commit adds a test that executes post-cutover governance through the new Wormhole receiver, proving the contract is still governable after the switch.

## Description

**Part 1: UpgradeContract (33 chains)**

Execute `GovernanceAction.UpgradeContract` on every chain. The new implementation contracts are already deployed; each payload carries only the 20-byte implementation address, so verifying this part means verifying that the bytecode at those addresses matches this repository.

**Part 2: SetDataSources (33 chains)**

Execute `GovernanceAction.SetDataSources` with a single data source on every chain:

```auto
emitterChain: 26 (Pythnet)
emitterAddress: 0x507974686e6574507974686e6574507974686e6574507974686e657450797468

```

It is the same upgraded Pyth Core data source being set on the SVM chains in the companion proposal.

This replaces the three data sources every Pyth Core contract currently carries.

After execution the contracts accept price updates from the upgraded Pyth Core data source only. Legacy Pythnet updates stop verifying.

**Part 3: SetWormholeAddress (33 chains)**

Execute `GovernanceAction.SetWormholeAddress` pointing each Pyth Core contract at its new Wormhole receiver. Every one of these receivers is already deployed and, at the time of writing, holds:

```auto
guardian set index: 0
guardians (5):
  0x41534bB176E461A3fb30479400f210549eCCE638
  0x6502987B62F21Cab7eb5cCd8f0173084b60d5B41
  0x44A3e8F6a382412CF6BB90A3F8106e68977476C9
  0xd9D7D4529577864352c9A6539a48238fCD447052
  0x1663a5A822336ece48559B1DFB1e93A017a7DAC3

```

The receivers run `ReceiverImplementationHalf`, a variant of the standard Wormhole receiver whose quorum is `n / 2 + 1` rather than `2n / 3 + 1`. With five guardians that is a **3-of-5** threshold, matching the `minimum_signatures = 3` configured on the SVM receivers.

**Execution order.** Instructions are grouped per chain as `UpgradeContract`, `SetDataSources`, `SetWormholeAddress`. The Pyth contract enforces strictly increasing Wormhole sequence numbers for governance instructions, so on every chain the ordering is guaranteed:

- the upgrade lands before the `SetWormholeAddress` that depends on it, and
- `SetDataSources` lands while the contract still verifies governance through the _old_ Wormhole receiver, which is the only receiver that can verify a VAA signed by the Wormhole guardians.

`SetWormholeAddress` must be the last action on each chain for that reason. Once it executes, all subsequent governance for that contract — not just price updates — is verified against the Pyth Pro guardian set.

**Governance data source is unchanged:** emitter `0x5635979a221c34931e32620b9293a463065555ea71fe97cd6237ade875b12e9e` on chain `1`, the Pythian Council multisig on Solana. What changes is the guardian set that signs its VAAs.

## Verification

**1. Decode the proposal.**

```auto
git clone <https://github.com/pyth-network/pyth-crosschain.git>
cd pyth-crosschain
pnpm install && pnpm turbo build --filter @pythnetwork/contract-manager
cd contract_manager
pnpm tsx scripts/check_proposal.ts --cluster mainnet-beta \
  --proposal 9yuPH43L5ouV4qBKEaZV8TYavZ3TLtePzaEJb4SKWgje

```

This walks all 99 instructions and prints, per chain: the code digest of the implementation each `UpgradeContract` points at; the proposed data source next to the contract’s current data sources; and the proxy digest, implementation digest, guardian set index and guardian set digest of the Wormhole receiver each `SetWormholeAddress` points at.

**2. Reproduce the three expected digests from source.**

```auto
cd target_chains/ethereum/contracts
pnpm run install-forge-deps
forge build

# Pyth Core implementation — every UpgradeContract target must match this
jq -r .deployedBytecode.object out/PythUpgradable.sol/PythUpgradable.json \
  | tr -d '\r\n' | cast keccak
# 0x7190f97e629ac8b731b8475c7819d77423b53215deaca6ed07fb89e414da135a

# Wormhole receiver proxy — every SetWormholeAddress target must match this
jq -r .deployedBytecode.object out/WormholeReceiver.sol/WormholeReceiver.json \
  | tr -d '\r\n' | cast keccak
# 0xdc3e90fa531e085a7df6e3fce1322f2ae67b47716d606097959e5d80afa764c6

# Wormhole receiver implementation (3-of-5 quorum variant)
jq -r .deployedBytecode.object \
  out/ReceiverImplementationHalf.sol/ReceiverImplementationHalf.json \
  | tr -d '\r\n' | cast keccak
# 0x672c872ab76094a205608519efb1f34a50662ced3410fdcfd45965bf41f6bef1

```

The `UpgradeContract` digest is taken with the contract’s own address zeroed out, so it is stable across chains.

**4. Cross-reference.** Pyth Core proxy addresses against the [Pyth Core EVM chainlist](https://docs.pyth.network/price-feeds/core/contract-addresses/evm).

## References

- [The Pyth Core upgrade](https://www.pyth.network/blog/the-pyth-core-upgrade)
- [Preparing for the Pyth Core upgrade](https://docs.pyth.network/price-feeds/core/upgrade/preparing)
- [OP-PIP-100: Pyth Core to Pyth Pro Migration](https://forum.pyth.network/t/passed-op-pip-100-pyth-core-to-pyth-pro-migration/2420)
- [OP-PIP-128: Pyth Core Sunset — Fee Zeroing & Balance Repatriation](https://forum.pyth.network/t/passed-op-pip-128-pyth-core-sunset-fee-zeroing-balance-repatriation/2662)
- [OP-PIP-130: Pyth Core — Additional Contract Upgrades and Fee Balance Repatriation](https://forum.pyth.network/t/passed-op-pip-130-pyth-core-additional-contract-upgrades-and-fee-balance-repatriation/2669)
- [Commit `4739bbc` — allow `SetWormholeAddress` without dual-verify](https://github.com/pyth-network/pyth-crosschain/commit/4739bbcb8f091ec1126deee40bf00f27df8b28f9)
- Companion proposal: Pyth Core upgrade on SVM chains
