governance.move 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. module pyth::governance {
  2. use pyth::governance_instruction;
  3. use pyth::governance_action;
  4. use pyth::set_governance_data_source;
  5. use pyth::set_data_sources;
  6. use pyth::set_stale_price_threshold;
  7. use pyth::set_fee_recipient;
  8. use pyth::state::{Self, State};
  9. use pyth::set_update_fee;
  10. use wormhole::vaa::{Self, VAA};
  11. use wormhole::bytes32::Bytes32;
  12. const E_INVALID_GOVERNANCE_ACTION: u64 = 0;
  13. const E_MUST_USE_CONTRACT_UPGRADE_MODULE_TO_DO_UPGRADES: u64 = 1;
  14. const E_CANNOT_EXECUTE_GOVERNANCE_ACTION_WITH_OBSOLETE_SEQUENCE_NUMBER: u64 = 2;
  15. const E_INVALID_GOVERNANCE_DATA_SOURCE: u64 = 4;
  16. // this struct does not have the store or key ability so it must be
  17. // used in the same txn chain in which it is created
  18. struct WormholeVAAVerificationReceipt{
  19. payload: vector<u8>,
  20. digest: Bytes32,
  21. sequence: u64, // used for replay protection
  22. }
  23. public fun take_payload(receipt: &WormholeVAAVerificationReceipt): vector<u8> {
  24. receipt.payload
  25. }
  26. public fun take_digest(receipt: &WormholeVAAVerificationReceipt): Bytes32 {
  27. receipt.digest
  28. }
  29. public fun take_sequence(receipt: &WormholeVAAVerificationReceipt): u64 {
  30. receipt.sequence
  31. }
  32. public fun destroy(receipt: WormholeVAAVerificationReceipt) {
  33. let WormholeVAAVerificationReceipt{payload: _, digest: _, sequence: _} = receipt;
  34. }
  35. // We define a custom verify_vaa function instead of using wormhole::governance_message::verify_vaa
  36. // because that function makes extra assumptions about the VAA payload headers. Pyth uses a
  37. // different header format compared to Wormhole, so
  38. public fun verify_vaa(
  39. pyth_state: &State,
  40. verified_vaa: VAA,
  41. ): WormholeVAAVerificationReceipt {
  42. state::assert_latest_only(pyth_state);
  43. let vaa_data_source = pyth::data_source::new((vaa::emitter_chain(&verified_vaa) as u64), vaa::emitter_address(&verified_vaa));
  44. // The emitter chain and address must correspond to the Pyth governance emitter chain and contract.
  45. assert!(
  46. pyth::state::is_valid_governance_data_source(pyth_state, vaa_data_source),
  47. E_INVALID_GOVERNANCE_DATA_SOURCE
  48. );
  49. let digest = vaa::digest(&verified_vaa);
  50. let sequence = vaa::sequence(&verified_vaa);
  51. let payload = vaa::take_payload(verified_vaa);
  52. WormholeVAAVerificationReceipt { payload, digest, sequence }
  53. }
  54. /// Execute a governance instruction other than contract upgrade, which is
  55. /// handled separately in the contract_upgrade.move module.
  56. public fun execute_governance_instruction(
  57. pyth_state : &mut State,
  58. receipt: WormholeVAAVerificationReceipt,
  59. ) {
  60. // This capability ensures that the current build version is used.
  61. let latest_only = state::assert_latest_only(pyth_state);
  62. // Get the sequence number of the governance VAA that was used to
  63. // generate the receipt.
  64. let sequence = receipt.sequence;
  65. // Require that new sequence number is greater than last executed sequence number.
  66. assert!(sequence > state::get_last_executed_governance_sequence(pyth_state),
  67. E_CANNOT_EXECUTE_GOVERNANCE_ACTION_WITH_OBSOLETE_SEQUENCE_NUMBER);
  68. // Update latest executed sequence number to current one.
  69. state::set_last_executed_governance_sequence(&latest_only, pyth_state, sequence);
  70. let payload = receipt.payload;
  71. destroy(receipt);
  72. let instruction = governance_instruction::from_byte_vec(payload);
  73. // Get the governance action.
  74. let action = governance_instruction::get_action(&instruction);
  75. // Dispatch the instruction to the appropriate handler.
  76. if (action == governance_action::new_contract_upgrade()) {
  77. abort(E_MUST_USE_CONTRACT_UPGRADE_MODULE_TO_DO_UPGRADES)
  78. } else if (action == governance_action::new_set_governance_data_source()) {
  79. set_governance_data_source::execute(&latest_only, pyth_state, governance_instruction::destroy(instruction));
  80. } else if (action == governance_action::new_set_data_sources()) {
  81. set_data_sources::execute(&latest_only, pyth_state, governance_instruction::destroy(instruction));
  82. } else if (action == governance_action::new_set_update_fee()) {
  83. set_update_fee::execute(&latest_only, pyth_state, governance_instruction::destroy(instruction));
  84. } else if (action == governance_action::new_set_stale_price_threshold()) {
  85. set_stale_price_threshold::execute(&latest_only, pyth_state, governance_instruction::destroy(instruction));
  86. } else if (action == governance_action::new_set_fee_recipient()) {
  87. set_fee_recipient::execute(&latest_only, pyth_state, governance_instruction::destroy(instruction));
  88. } else {
  89. governance_instruction::destroy(instruction);
  90. assert!(false, E_INVALID_GOVERNANCE_ACTION);
  91. }
  92. }
  93. }