| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- // contracts/Bridge.sol
- // SPDX-License-Identifier: Apache 2
- pragma solidity ^0.8.0;
- import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
- import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
- import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
- import "../libraries/external/BytesLib.sol";
- import "./BridgeGetters.sol";
- import "./BridgeSetters.sol";
- import "./BridgeStructs.sol";
- import "./token/Token.sol";
- import "./token/TokenImplementation.sol";
- import "../interfaces/IWormhole.sol";
- contract BridgeGovernance is BridgeGetters, BridgeSetters, ERC1967Upgrade {
- using BytesLib for bytes;
- // "TokenBridge" (left padded)
- bytes32 constant module = 0x000000000000000000000000000000000000000000546f6b656e427269646765;
- // Execute a RegisterChain governance message
- function registerChain(bytes memory encodedVM) public {
- (IWormhole.VM memory vm, bool valid, string memory reason) = verifyGovernanceVM(encodedVM);
- require(valid, reason);
- setGovernanceActionConsumed(vm.hash);
- BridgeStructs.RegisterChain memory chain = parseRegisterChain(vm.payload);
- require(chain.chainId == chainId() || chain.chainId == 0, "invalid chain id");
- require(bridgeContracts(chain.emitterChainID) == bytes32(0), "chain already registered");
- setBridgeImplementation(chain.emitterChainID, chain.emitterAddress);
- }
- // Execute a UpgradeContract governance message
- function upgrade(bytes memory encodedVM) public {
- (IWormhole.VM memory vm, bool valid, string memory reason) = verifyGovernanceVM(encodedVM);
- require(valid, reason);
- setGovernanceActionConsumed(vm.hash);
- BridgeStructs.UpgradeContract memory implementation = parseUpgrade(vm.payload);
- require(implementation.chainId == chainId(), "wrong chain id");
- upgradeImplementation(address(uint160(uint256(implementation.newContract))));
- }
- function verifyGovernanceVM(bytes memory encodedVM) internal view returns (IWormhole.VM memory parsedVM, bool isValid, string memory invalidReason){
- (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVM);
- if (!valid) {
- return (vm, valid, reason);
- }
- if (vm.emitterChainId != governanceChainId()) {
- return (vm, false, "wrong governance chain");
- }
- if (vm.emitterAddress != governanceContract()) {
- return (vm, false, "wrong governance contract");
- }
- if (governanceActionIsConsumed(vm.hash)) {
- return (vm, false, "governance action already consumed");
- }
- return (vm, true, "");
- }
- event ContractUpgraded(address indexed oldContract, address indexed newContract);
- function upgradeImplementation(address newImplementation) internal {
- address currentImplementation = _getImplementation();
- _upgradeTo(newImplementation);
- // Call initialize function of the new implementation
- (bool success, bytes memory reason) = newImplementation.delegatecall(abi.encodeWithSignature("initialize()"));
- require(success, string(reason));
- emit ContractUpgraded(currentImplementation, newImplementation);
- }
- function parseRegisterChain(bytes memory encoded) public pure returns (BridgeStructs.RegisterChain memory chain) {
- uint index = 0;
- // governance header
- chain.module = encoded.toBytes32(index);
- index += 32;
- require(chain.module == module, "invalid RegisterChain: wrong module");
- chain.action = encoded.toUint8(index);
- index += 1;
- require(chain.action == 1, "invalid RegisterChain: wrong action");
- chain.chainId = encoded.toUint16(index);
- index += 2;
- // payload
- chain.emitterChainID = encoded.toUint16(index);
- index += 2;
- chain.emitterAddress = encoded.toBytes32(index);
- index += 32;
- require(encoded.length == index, "invalid RegisterChain: wrong length");
- }
- function parseUpgrade(bytes memory encoded) public pure returns (BridgeStructs.UpgradeContract memory chain) {
- uint index = 0;
- // governance header
- chain.module = encoded.toBytes32(index);
- index += 32;
- require(chain.module == module, "invalid UpgradeContract: wrong module");
- chain.action = encoded.toUint8(index);
- index += 1;
- require(chain.action == 2, "invalid UpgradeContract: wrong action");
- chain.chainId = encoded.toUint16(index);
- index += 2;
- // payload
- chain.newContract = encoded.toBytes32(index);
- index += 32;
- require(encoded.length == index, "invalid UpgradeContract: wrong length");
- }
- }
|