90 lines
3.0 KiB
Solidity
90 lines
3.0 KiB
Solidity
// contracts/Bridge.sol
|
|
// SPDX-License-Identifier: Apache 2
|
|
|
|
pragma solidity ^0.8.0;
|
|
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
|
|
|
|
import "../libraries/external/BytesLib.sol";
|
|
|
|
import "./PythGetters.sol";
|
|
import "./PythSetters.sol";
|
|
import "./PythStructs.sol";
|
|
|
|
import "../interfaces/IWormhole.sol";
|
|
|
|
contract PythGovernance is PythGetters, PythSetters, ERC1967Upgrade {
|
|
using BytesLib for bytes;
|
|
|
|
bytes32 constant module = 0x0000000000000000000000000000000000000000000000000000000050797468;
|
|
|
|
// 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);
|
|
|
|
PythStructs.UpgradeContract memory implementation = parseContractUpgrade(vm.payload);
|
|
|
|
require(implementation.module == module, "wrong module");
|
|
require(implementation.chain == chainId(), "wrong chain id");
|
|
|
|
upgradeImplementation(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 parseContractUpgrade(bytes memory encodedUpgrade) public pure returns (PythStructs.UpgradeContract memory cu) {
|
|
uint index = 0;
|
|
|
|
cu.module = encodedUpgrade.toBytes32(index);
|
|
index += 32;
|
|
|
|
cu.action = encodedUpgrade.toUint8(index);
|
|
index += 1;
|
|
|
|
require(cu.action == 1, "invalid ContractUpgrade 1");
|
|
|
|
cu.chain = encodedUpgrade.toUint16(index);
|
|
index += 2;
|
|
|
|
cu.newContract = address(uint160(uint256(encodedUpgrade.toBytes32(index))));
|
|
index += 32;
|
|
|
|
require(encodedUpgrade.length == index, "invalid ContractUpgrade 2");
|
|
}
|
|
}
|