Constructor for the executor contract.
Runs only during deployment. Sets up the guardian set, chain ID, and emitter configuration.
Two emitters are configured separately:
owner_emitter_* authorizes governance actions executed against
target contracts via [Self::execute_governance_action].gs_upgrade_emitter_* (the guardian-set-upgrade emitter)
authorizes guardian set upgrade VAAs handled by
[Self::update_guardian_set]. In production this is the Wormhole
core bridge governance emitter, which is distinct from the Pyth
governance emitter used to issue PTGM actions.fn __constructor(
env: soroban_sdk::Env,
chain_id: u32,
owner_emitter_chain: u32,
owner_emitter_address: soroban_sdk::BytesN<32>,
gs_upgrade_emitter_chain: u32,
gs_upgrade_emitter_address: soroban_sdk::BytesN<32>,
initial_guardian_set: soroban_sdk::Vec>,
guardian_set_index: u32,
) -> Result<(), ContractError>
Process a guardian set upgrade VAA.
This is a self-governance mechanism: the current guardian set signs a VAA that authorizes a new guardian set. The VAA payload follows the Wormhole core governance format:
[32 bytes] module ("Core" right-padded)
[1 byte] action (2 = guardian set upgrade)
[2 bytes] target chain (0 = all chains)
[4 bytes] new guardian set index (BE u32)
[1 byte] num guardians
For each guardian:
[20 bytes] Ethereum address
Guardian set upgrades are governance actions and require the current
guardian set: the VAA's guardian_set_index must equal the stored
index, otherwise it is rejected with InvalidGuardianSetIndex. The
24-hour grace window in verify_vaa — during which a retired set's VAAs
are still accepted — applies to non-governance message VAAs only and
does not extend to this function.
fn update_guardian_set(
env: soroban_sdk::Env,
vaa_bytes: soroban_sdk::Bytes,
) -> Result<(), ContractError>
Execute a governance action from a Wormhole VAA containing a PTGM payload.
This verifies the VAA, validates the emitter matches the stored owner, enforces replay protection via strictly increasing sequence numbers, parses the PTGM governance instruction, and dispatches a cross-contract call to the target contract.
Like Pyth's other governance receivers, this relies on the generic
verify_vaa path and so accepts a retired guardian set within its
24-hour grace window — it does not additionally require the current
set. (The self-referential update_guardian_set upgrade path does
require the current set; see its docs.)
This entry point is permissionless and never calls require_auth on the
submitter, so an authorization that a Call target requires cannot be
nested under the governance action — it must be submitted as its own
top-level authorization entry, which anyone observing the transaction
can lift into a transaction of their own and consume independently. The
only current target, `PythLazerCont
fn execute_governance_action(
env: soroban_sdk::Env,
vaa_bytes: soroban_sdk::Bytes,
) -> Result<(), ContractError>