PythGovernance.sol 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // contracts/Governance.sol
  2. // SPDX-License-Identifier: Apache 2
  3. pragma solidity ^0.8.0;
  4. import "./PythGovernanceInstructions.sol";
  5. import "./PythInternalStructs.sol";
  6. import "./PythGetters.sol";
  7. import "./PythSetters.sol";
  8. import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
  9. /**
  10. * @dev `Governance` defines a means to enacting changes to the Pyth contract.
  11. */
  12. abstract contract PythGovernance is PythGetters, PythSetters, PythGovernanceInstructions {
  13. event ContractUpgraded(address oldImplementation, address newImplementation);
  14. event GovernanceDataSourceSet(PythInternalStructs.DataSource oldDataSource, PythInternalStructs.DataSource newDataSource,
  15. uint64 initialSequence);
  16. event DataSourcesSet(PythInternalStructs.DataSource[] oldDataSources, PythInternalStructs.DataSource[] newDataSources);
  17. event FeeSet(uint oldFee, uint newFee);
  18. event ValidPeriodSet(uint oldValidPeriod, uint newValidPeriod);
  19. function verifyGovernanceVM(bytes memory encodedVM) internal returns (IWormhole.VM memory parsedVM){
  20. (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVM);
  21. require(valid, reason);
  22. require(isValidGovernanceDataSource(vm.emitterChainId, vm.emitterAddress), "VAA is not coming from the governance data source");
  23. require(vm.sequence > lastExecutedGovernanceSequence(), "VAA is older than the last executed governance VAA");
  24. setLastExecutedGovernanceSequence(vm.sequence);
  25. return vm;
  26. }
  27. function executeGovernanceInstruction(bytes calldata encodedVM) public {
  28. IWormhole.VM memory vm = verifyGovernanceVM(encodedVM);
  29. GovernanceInstruction memory gi = parseGovernanceInstruction(vm.payload);
  30. require(gi.targetChainId == chainId() || gi.targetChainId == 0, "invalid target chain for this governance instruction");
  31. if (gi.action == GovernanceAction.UpgradeContract) {
  32. require(gi.targetChainId != 0, "upgrade with chain id 0 is not possible");
  33. upgradeContract(gi.payload);
  34. } else if (gi.action == GovernanceAction.SetGovernanceDataSource) {
  35. setGovernanceDataSource(gi.payload);
  36. } else if (gi.action == GovernanceAction.SetDataSources) {
  37. setDataSources(gi.payload);
  38. } else if (gi.action == GovernanceAction.SetFee) {
  39. setFee(gi.payload);
  40. } else if (gi.action == GovernanceAction.SetValidPeriod) {
  41. setValidPeriod(gi.payload);
  42. } else {
  43. revert("invalid governance action");
  44. }
  45. }
  46. function upgradeContract(bytes memory encodedPayload) internal {
  47. UpgradeContractPayload memory payload = parseUpgradeContractPayload(encodedPayload);
  48. // This contract does not have enough access to execute this, it should be executed on the
  49. // upgradable
  50. upgradeUpgradableContract(payload);
  51. }
  52. function upgradeUpgradableContract(UpgradeContractPayload memory payload) virtual internal;
  53. function setGovernanceDataSource(bytes memory encodedPayload) internal {
  54. SetGovernanceDataSourcePayload memory payload = parseSetGovernanceDataSourcePayload(encodedPayload);
  55. PythInternalStructs.DataSource memory oldGovernanceDatSource = governanceDataSource();
  56. setGovernanceDataSource(payload.newGovernanceDataSource);
  57. setLastExecutedGovernanceSequence(payload.initialSequence);
  58. emit GovernanceDataSourceSet(oldGovernanceDatSource, governanceDataSource(), lastExecutedGovernanceSequence());
  59. }
  60. function setDataSources(bytes memory encodedPayload) internal {
  61. SetDataSourcesPayload memory payload = parseSetDataSourcesPayload(encodedPayload);
  62. PythInternalStructs.DataSource[] memory oldDataSources = validDataSources();
  63. for (uint i = 0; i < oldDataSources.length; i += 1) {
  64. _state.isValidDataSource[hashDataSource(oldDataSources[i])] = false;
  65. }
  66. delete _state.validDataSources;
  67. for (uint i = 0; i < payload.dataSources.length; i++) {
  68. _state.validDataSources.push(payload.dataSources[i]);
  69. _state.isValidDataSource[hashDataSource(payload.dataSources[i])] = true;
  70. }
  71. emit DataSourcesSet(oldDataSources, validDataSources());
  72. }
  73. function setFee(bytes memory encodedPayload) internal {
  74. SetFeePayload memory payload = parseSetFeePayload(encodedPayload);
  75. uint oldFee = singleUpdateFeeInWei();
  76. setSingleUpdateFeeInWei(payload.newFee);
  77. emit FeeSet(oldFee, singleUpdateFeeInWei());
  78. }
  79. function setValidPeriod(bytes memory encodedPayload) internal {
  80. SetValidPeriodPayload memory payload = parseSetValidPeriodPayload(encodedPayload);
  81. uint oldValidPeriod = validTimePeriodSeconds();
  82. setValidTimePeriodSeconds(payload.newValidPeriod);
  83. emit ValidPeriodSet(oldValidPeriod, validTimePeriodSeconds());
  84. }
  85. }