pyth-crosschain/ethereum/contracts/wormhole-receiver/ReceiverGovernance.sol

96 lines
3.3 KiB
Solidity
Raw Normal View History

// contracts/Governance.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "./ReceiverStructs.sol";
import "./ReceiverGovernanceStructs.sol";
import "./ReceiverMessages.sol";
import "./ReceiverSetters.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
abstract contract ReceiverGovernance is ReceiverGovernanceStructs, ReceiverMessages, ReceiverSetters, ERC1967Upgrade {
event ContractUpgraded(address indexed oldContract, address indexed newContract);
event OwnershipTransfered(address indexed oldOwner, address indexed newOwner);
// "Core" (left padded)
bytes32 constant module = 0x00000000000000000000000000000000000000000000000000000000436f7265;
function submitNewGuardianSet(bytes memory _vm) public {
ReceiverStructs.VM memory vm = parseVM(_vm);
(bool isValid, string memory reason) = verifyGovernanceVM(vm);
require(isValid, reason);
ReceiverGovernanceStructs.GuardianSetUpgrade memory upgrade = parseGuardianSetUpgrade(vm.payload);
require(upgrade.module == module, "invalid Module");
require(upgrade.newGuardianSet.keys.length > 0, "new guardian set is empty");
require(upgrade.newGuardianSetIndex == getCurrentGuardianSetIndex() + 1, "index must increase in steps of 1");
setGovernanceActionConsumed(vm.hash);
expireGuardianSet(getCurrentGuardianSetIndex());
storeGuardianSet(upgrade.newGuardianSet, upgrade.newGuardianSetIndex);
updateGuardianSetIndex(upgrade.newGuardianSetIndex);
}
function upgradeImplementation(address newImplementation) public onlyOwner {
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 verifyGovernanceVM(ReceiverStructs.VM memory vm) internal view returns (bool, string memory){
// validate vm
(bool isValid, string memory reason) = verifyVM(vm);
if (!isValid){
return (false, reason);
}
// only current guardianset can sign governance packets
if (vm.guardianSetIndex != getCurrentGuardianSetIndex()) {
return (false, "not signed by current guardian set");
}
// verify source
if (uint16(vm.emitterChainId) != governanceChainId()) {
return (false, "wrong governance chain");
}
if (vm.emitterAddress != governanceContract()) {
return (false, "wrong governance contract");
}
// prevent re-entry
if (governanceActionIsConsumed(vm.hash)){
return (false, "governance action already consumed");
}
return (true, "");
}
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0), "new owner cannot be the zero address");
address currentOwner = owner();
setOwner(newOwner);
emit OwnershipTransfered(currentOwner, newOwner);
}
modifier onlyOwner() {
require(owner() == msg.sender, "caller is not the owner");
_;
}
}