Governance.sol 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // contracts/Governance.sol
  2. // SPDX-License-Identifier: Apache 2
  3. pragma solidity ^0.8.0;
  4. import "./Structs.sol";
  5. import "./GovernanceStructs.sol";
  6. import "./Messages.sol";
  7. import "./Setters.sol";
  8. import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
  9. abstract contract Governance is
  10. GovernanceStructs,
  11. Messages,
  12. Setters,
  13. ERC1967Upgrade
  14. {
  15. event ContractUpgraded(
  16. address indexed oldContract,
  17. address indexed newContract
  18. );
  19. event GuardianSetAdded(uint32 indexed index);
  20. // "Core" (left padded)
  21. bytes32 constant module =
  22. 0x00000000000000000000000000000000000000000000000000000000436f7265;
  23. function submitContractUpgrade(bytes memory _vm) public {
  24. Structs.VM memory vm = parseVM(_vm);
  25. (bool isValid, string memory reason) = verifyGovernanceVM(vm);
  26. require(isValid, reason);
  27. GovernanceStructs.ContractUpgrade memory upgrade = parseContractUpgrade(
  28. vm.payload
  29. );
  30. require(upgrade.module == module, "Invalid Module");
  31. require(upgrade.chain == chainId(), "Invalid Chain");
  32. setGovernanceActionConsumed(vm.hash);
  33. upgradeImplementation(upgrade.newContract);
  34. }
  35. function submitSetMessageFee(bytes memory _vm) public {
  36. Structs.VM memory vm = parseVM(_vm);
  37. (bool isValid, string memory reason) = verifyGovernanceVM(vm);
  38. require(isValid, reason);
  39. GovernanceStructs.SetMessageFee memory upgrade = parseSetMessageFee(
  40. vm.payload
  41. );
  42. require(upgrade.module == module, "Invalid Module");
  43. require(upgrade.chain == chainId(), "Invalid Chain");
  44. setGovernanceActionConsumed(vm.hash);
  45. setMessageFee(upgrade.messageFee);
  46. }
  47. function submitNewGuardianSet(bytes memory _vm) public {
  48. Structs.VM memory vm = parseVM(_vm);
  49. (bool isValid, string memory reason) = verifyGovernanceVM(vm);
  50. require(isValid, reason);
  51. GovernanceStructs.GuardianSetUpgrade
  52. memory upgrade = parseGuardianSetUpgrade(vm.payload);
  53. require(upgrade.module == module, "invalid Module");
  54. require(
  55. upgrade.chain == chainId() || upgrade.chain == 0,
  56. "invalid Chain"
  57. );
  58. require(
  59. upgrade.newGuardianSet.keys.length > 0,
  60. "new guardian set is empty"
  61. );
  62. require(
  63. upgrade.newGuardianSetIndex == getCurrentGuardianSetIndex() + 1,
  64. "index must increase in steps of 1"
  65. );
  66. setGovernanceActionConsumed(vm.hash);
  67. expireGuardianSet(getCurrentGuardianSetIndex());
  68. storeGuardianSet(upgrade.newGuardianSet, upgrade.newGuardianSetIndex);
  69. updateGuardianSetIndex(upgrade.newGuardianSetIndex);
  70. }
  71. function submitTransferFees(bytes memory _vm) public {
  72. Structs.VM memory vm = parseVM(_vm);
  73. (bool isValid, string memory reason) = verifyGovernanceVM(vm);
  74. require(isValid, reason);
  75. GovernanceStructs.TransferFees memory transfer = parseTransferFees(
  76. vm.payload
  77. );
  78. require(transfer.module == module, "invalid Module");
  79. require(
  80. transfer.chain == chainId() || transfer.chain == 0,
  81. "invalid Chain"
  82. );
  83. setGovernanceActionConsumed(vm.hash);
  84. address payable recipient = payable(
  85. address(uint160(uint256(transfer.recipient)))
  86. );
  87. recipient.transfer(transfer.amount);
  88. }
  89. function upgradeImplementation(address newImplementation) internal {
  90. address currentImplementation = _getImplementation();
  91. _upgradeTo(newImplementation);
  92. // Call initialize function of the new implementation
  93. (bool success, bytes memory reason) = newImplementation.delegatecall(
  94. abi.encodeWithSignature("initialize()")
  95. );
  96. require(success, string(reason));
  97. emit ContractUpgraded(currentImplementation, newImplementation);
  98. }
  99. function verifyGovernanceVM(
  100. Structs.VM memory vm
  101. ) internal view returns (bool, string memory) {
  102. // validate vm
  103. (bool isValid, string memory reason) = verifyVM(vm);
  104. if (!isValid) {
  105. return (false, reason);
  106. }
  107. // only current guardianset can sign governance packets
  108. if (vm.guardianSetIndex != getCurrentGuardianSetIndex()) {
  109. return (false, "not signed by current guardian set");
  110. }
  111. // verify source
  112. if (uint16(vm.emitterChainId) != governanceChainId()) {
  113. return (false, "wrong governance chain");
  114. }
  115. if (vm.emitterAddress != governanceContract()) {
  116. return (false, "wrong governance contract");
  117. }
  118. // prevent re-entry
  119. if (governanceActionIsConsumed(vm.hash)) {
  120. return (false, "governance action already consumed");
  121. }
  122. return (true, "");
  123. }
  124. }