131 lines
4.5 KiB
Solidity
131 lines
4.5 KiB
Solidity
// contracts/Governance.sol
|
|
// SPDX-License-Identifier: Apache 2
|
|
|
|
pragma solidity ^0.8.0;
|
|
|
|
import "./Structs.sol";
|
|
import "./GovernanceStructs.sol";
|
|
import "./Messages.sol";
|
|
import "./Setters.sol";
|
|
|
|
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
|
|
|
|
abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upgrade {
|
|
event ContractUpgraded(address indexed oldContract, address indexed newContract);
|
|
event GuardianSetAdded(uint32 indexed index);
|
|
|
|
// "Core" (left padded)
|
|
bytes32 constant module = 0x00000000000000000000000000000000000000000000000000000000436f7265;
|
|
|
|
function submitContractUpgrade(bytes memory _vm) public {
|
|
Structs.VM memory vm = parseVM(_vm);
|
|
|
|
(bool isValid, string memory reason) = verifyGovernanceVM(vm);
|
|
require(isValid, reason);
|
|
|
|
GovernanceStructs.ContractUpgrade memory upgrade = parseContractUpgrade(vm.payload);
|
|
|
|
require(upgrade.module == module, "Invalid Module");
|
|
require(upgrade.chain == chainId(), "Invalid Chain");
|
|
|
|
setGovernanceActionConsumed(vm.hash);
|
|
|
|
upgradeImplementation(upgrade.newContract);
|
|
}
|
|
|
|
function submitSetMessageFee(bytes memory _vm) public {
|
|
Structs.VM memory vm = parseVM(_vm);
|
|
|
|
(bool isValid, string memory reason) = verifyGovernanceVM(vm);
|
|
require(isValid, reason);
|
|
|
|
GovernanceStructs.SetMessageFee memory upgrade = parseSetMessageFee(vm.payload);
|
|
|
|
require(upgrade.module == module, "Invalid Module");
|
|
require(upgrade.chain == chainId(), "Invalid Chain");
|
|
|
|
setGovernanceActionConsumed(vm.hash);
|
|
|
|
setMessageFee(upgrade.messageFee);
|
|
}
|
|
|
|
function submitNewGuardianSet(bytes memory _vm) public {
|
|
Structs.VM memory vm = parseVM(_vm);
|
|
|
|
(bool isValid, string memory reason) = verifyGovernanceVM(vm);
|
|
require(isValid, reason);
|
|
|
|
GovernanceStructs.GuardianSetUpgrade memory upgrade = parseGuardianSetUpgrade(vm.payload);
|
|
|
|
require(upgrade.module == module, "invalid Module");
|
|
require(upgrade.chain == chainId() || upgrade.chain == 0, "invalid Chain");
|
|
|
|
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 submitTransferFees(bytes memory _vm) public {
|
|
Structs.VM memory vm = parseVM(_vm);
|
|
|
|
(bool isValid, string memory reason) = verifyGovernanceVM(vm);
|
|
require(isValid, reason);
|
|
|
|
GovernanceStructs.TransferFees memory transfer = parseTransferFees(vm.payload);
|
|
|
|
require(transfer.module == module, "invalid Module");
|
|
require(transfer.chain == chainId() || transfer.chain == 0, "invalid Chain");
|
|
|
|
setGovernanceActionConsumed(vm.hash);
|
|
|
|
address payable recipient = payable(address(uint160(uint256(transfer.recipient))));
|
|
|
|
recipient.transfer(transfer.amount);
|
|
}
|
|
|
|
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 verifyGovernanceVM(Structs.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, "");
|
|
}
|
|
} |