BridgeGovernance.sol 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // contracts/Bridge.sol
  2. // SPDX-License-Identifier: Apache 2
  3. pragma solidity ^0.8.0;
  4. import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
  5. import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
  6. import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
  7. import "../libraries/external/BytesLib.sol";
  8. import "./BridgeGetters.sol";
  9. import "./BridgeSetters.sol";
  10. import "./BridgeStructs.sol";
  11. import "./token/Token.sol";
  12. import "./token/TokenImplementation.sol";
  13. import "../interfaces/IWormhole.sol";
  14. contract BridgeGovernance is BridgeGetters, BridgeSetters, ERC1967Upgrade {
  15. using BytesLib for bytes;
  16. // "TokenBridge" (left padded)
  17. bytes32 constant module = 0x000000000000000000000000000000000000000000546f6b656e427269646765;
  18. // Execute a RegisterChain governance message
  19. function registerChain(bytes memory encodedVM) public {
  20. (IWormhole.VM memory vm, bool valid, string memory reason) = verifyGovernanceVM(encodedVM);
  21. require(valid, reason);
  22. setGovernanceActionConsumed(vm.hash);
  23. BridgeStructs.RegisterChain memory chain = parseRegisterChain(vm.payload);
  24. require(chain.chainId == chainId() || chain.chainId == 0, "invalid chain id");
  25. require(bridgeContracts(chain.emitterChainID) == bytes32(0), "chain already registered");
  26. setBridgeImplementation(chain.emitterChainID, chain.emitterAddress);
  27. }
  28. // Execute a UpgradeContract governance message
  29. function upgrade(bytes memory encodedVM) public {
  30. (IWormhole.VM memory vm, bool valid, string memory reason) = verifyGovernanceVM(encodedVM);
  31. require(valid, reason);
  32. setGovernanceActionConsumed(vm.hash);
  33. BridgeStructs.UpgradeContract memory implementation = parseUpgrade(vm.payload);
  34. require(implementation.chainId == chainId(), "wrong chain id");
  35. upgradeImplementation(address(uint160(uint256(implementation.newContract))));
  36. }
  37. function verifyGovernanceVM(bytes memory encodedVM) internal view returns (IWormhole.VM memory parsedVM, bool isValid, string memory invalidReason){
  38. (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVM);
  39. if (!valid) {
  40. return (vm, valid, reason);
  41. }
  42. if (vm.emitterChainId != governanceChainId()) {
  43. return (vm, false, "wrong governance chain");
  44. }
  45. if (vm.emitterAddress != governanceContract()) {
  46. return (vm, false, "wrong governance contract");
  47. }
  48. if (governanceActionIsConsumed(vm.hash)) {
  49. return (vm, false, "governance action already consumed");
  50. }
  51. return (vm, true, "");
  52. }
  53. event ContractUpgraded(address indexed oldContract, address indexed newContract);
  54. function upgradeImplementation(address newImplementation) internal {
  55. address currentImplementation = _getImplementation();
  56. _upgradeTo(newImplementation);
  57. // Call initialize function of the new implementation
  58. (bool success, bytes memory reason) = newImplementation.delegatecall(abi.encodeWithSignature("initialize()"));
  59. require(success, string(reason));
  60. emit ContractUpgraded(currentImplementation, newImplementation);
  61. }
  62. function parseRegisterChain(bytes memory encoded) public pure returns (BridgeStructs.RegisterChain memory chain) {
  63. uint index = 0;
  64. // governance header
  65. chain.module = encoded.toBytes32(index);
  66. index += 32;
  67. require(chain.module == module, "invalid RegisterChain: wrong module");
  68. chain.action = encoded.toUint8(index);
  69. index += 1;
  70. require(chain.action == 1, "invalid RegisterChain: wrong action");
  71. chain.chainId = encoded.toUint16(index);
  72. index += 2;
  73. // payload
  74. chain.emitterChainID = encoded.toUint16(index);
  75. index += 2;
  76. chain.emitterAddress = encoded.toBytes32(index);
  77. index += 32;
  78. require(encoded.length == index, "invalid RegisterChain: wrong length");
  79. }
  80. function parseUpgrade(bytes memory encoded) public pure returns (BridgeStructs.UpgradeContract memory chain) {
  81. uint index = 0;
  82. // governance header
  83. chain.module = encoded.toBytes32(index);
  84. index += 32;
  85. require(chain.module == module, "invalid UpgradeContract: wrong module");
  86. chain.action = encoded.toUint8(index);
  87. index += 1;
  88. require(chain.action == 2, "invalid UpgradeContract: wrong action");
  89. chain.chainId = encoded.toUint16(index);
  90. index += 2;
  91. // payload
  92. chain.newContract = encoded.toBytes32(index);
  93. index += 32;
  94. require(encoded.length == index, "invalid UpgradeContract: wrong length");
  95. }
  96. }