Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add utils for DecentralizeGovernance transaction #829

Merged
merged 2 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions l1-contracts/deploy-scripts/EIP712Utils.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

library EIP712Utils {
bytes32 private constant TYPE_HASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");

function buildDomainHash(
address _verifyingContract,
string memory _name,
string memory _version
) internal view returns (bytes32) {
return
keccak256(
// solhint-disable-next-line func-named-parameters
abi.encode(
TYPE_HASH,
keccak256(bytes(_name)),
keccak256(bytes(_version)),
block.chainid,
_verifyingContract
)
);
}

function buildDigest(bytes32 _domainHash, bytes32 _message) internal view returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", _domainHash, _message));
}
}
133 changes: 133 additions & 0 deletions l1-contracts/deploy-scripts/Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@ import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA} from "contracts/common/Config.sol";
import {L2_DEPLOYER_SYSTEM_CONTRACT_ADDR} from "contracts/common/L2ContractAddresses.sol";
import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol";
import {IChainAdmin} from "contracts/governance/IChainAdmin.sol";
import {EIP712Utils} from "./EIP712Utils.sol";
import {IProtocolUpgradeHandler} from "./interfaces/IProtocolUpgradeHandler.sol";
import {IEmergencyUpgrageBoard} from "./interfaces/IEmergencyUpgrageBoard.sol";
import {IMultisig} from "./interfaces/IMultisig.sol";
import {ISafe} from "./interfaces/ISafe.sol";

/// @dev EIP-712 TypeHash for the emergency protocol upgrade execution approved by the guardians.
bytes32 constant EXECUTE_EMERGENCY_UPGRADE_GUARDIANS_TYPEHASH = keccak256(
"ExecuteEmergencyUpgradeGuardians(bytes32 id)"
);

/// @dev EIP-712 TypeHash for the emergency protocol upgrade execution approved by the Security Council.
bytes32 constant EXECUTE_EMERGENCY_UPGRADE_SECURITY_COUNCIL_TYPEHASH = keccak256(
"ExecuteEmergencyUpgradeSecurityCouncil(bytes32 id)"
);

/// @dev EIP-712 TypeHash for the emergency protocol upgrade execution approved by the ZK Foundation.
bytes32 constant EXECUTE_EMERGENCY_UPGRADE_ZK_FOUNDATION_TYPEHASH = keccak256(
"ExecuteEmergencyUpgradeZKFoundation(bytes32 id)"
);

library Utils {
// Cheatcodes address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.
Expand Down Expand Up @@ -324,4 +344,117 @@ library Utils {
}
vm.stopBroadcast();
}

function executeEmergencyProtocolUpgrade(
IProtocolUpgradeHandler _protocolUpgradeHandler,
Vm.Wallet memory _governorWallet,
IProtocolUpgradeHandler.Call[] memory _calls,
bytes32 _salt
) internal returns (bytes memory) {
bytes32 upgradeId;
bytes32 emergencyUpgradeBoardDigest;
{
address emergencyUpgradeBoard = _protocolUpgradeHandler.emergencyUpgradeBoard();
IProtocolUpgradeHandler.UpgradeProposal memory upgradeProposal = IProtocolUpgradeHandler.UpgradeProposal({
calls: _calls,
salt: _salt,
executor: emergencyUpgradeBoard
});
upgradeId = keccak256(abi.encode(upgradeProposal));
emergencyUpgradeBoardDigest = EIP712Utils.buildDomainHash(
emergencyUpgradeBoard,
"EmergencyUpgradeBoard",
"1"
);
}

bytes memory guardiansSignatures;
{
address[] memory guardiansMembers = new address[](8);
{
IMultisig guardians = IMultisig(_protocolUpgradeHandler.guardians());
for (uint256 i = 0; i < 8; i++) {
guardiansMembers[i] = guardians.members(i);
}
}
bytes[] memory guardiansRawSignatures = new bytes[](8);
for (uint256 i = 0; i < 8; i++) {
bytes32 safeDigest;
{
bytes32 guardiansDigest = EIP712Utils.buildDigest(
emergencyUpgradeBoardDigest,
keccak256(abi.encode(EXECUTE_EMERGENCY_UPGRADE_GUARDIANS_TYPEHASH, upgradeId))
);
safeDigest = ISafe(guardiansMembers[i]).getMessageHash(abi.encode(guardiansDigest));
}

(uint8 v, bytes32 r, bytes32 s) = vm.sign(_governorWallet, safeDigest);
guardiansRawSignatures[i] = abi.encodePacked(r, s, v);
}
guardiansSignatures = abi.encode(guardiansMembers, guardiansRawSignatures);
}

bytes memory securityCouncilSignatures;
{
address[] memory securityCouncilMembers = new address[](12);
{
IMultisig securityCouncil = IMultisig(_protocolUpgradeHandler.securityCouncil());
for (uint256 i = 0; i < 12; i++) {
securityCouncilMembers[i] = securityCouncil.members(i);
}
}
bytes[] memory securityCouncilRawSignatures = new bytes[](12);
for (uint256 i = 0; i < securityCouncilMembers.length; i++) {
bytes32 safeDigest;
{
bytes32 securityCouncilDigest = EIP712Utils.buildDigest(
emergencyUpgradeBoardDigest,
keccak256(abi.encode(EXECUTE_EMERGENCY_UPGRADE_SECURITY_COUNCIL_TYPEHASH, upgradeId))
);
safeDigest = ISafe(securityCouncilMembers[i]).getMessageHash(abi.encode(securityCouncilDigest));
}
{
(uint8 v, bytes32 r, bytes32 s) = vm.sign(_governorWallet, safeDigest);
securityCouncilRawSignatures[i] = abi.encodePacked(r, s, v);
}
}
securityCouncilSignatures = abi.encode(securityCouncilMembers, securityCouncilRawSignatures);
}

bytes memory zkFoundationSignature;
{
ISafe zkFoundation;
{
IEmergencyUpgrageBoard emergencyUpgradeBoard = IEmergencyUpgrageBoard(
_protocolUpgradeHandler.emergencyUpgradeBoard()
);
zkFoundation = ISafe(emergencyUpgradeBoard.ZK_FOUNDATION_SAFE());
}
bytes32 zkFoundationDigest = EIP712Utils.buildDigest(
emergencyUpgradeBoardDigest,
keccak256(abi.encode(EXECUTE_EMERGENCY_UPGRADE_ZK_FOUNDATION_TYPEHASH, upgradeId))
);
bytes32 safeDigest = ISafe(zkFoundation).getMessageHash(abi.encode(zkFoundationDigest));
{
(uint8 v, bytes32 r, bytes32 s) = vm.sign(_governorWallet, safeDigest);
zkFoundationSignature = abi.encodePacked(r, s, v);
}
}

{
vm.startBroadcast();
IEmergencyUpgrageBoard emergencyUpgradeBoard = IEmergencyUpgrageBoard(
_protocolUpgradeHandler.emergencyUpgradeBoard()
);
// solhint-disable-next-line func-named-parameters
emergencyUpgradeBoard.executeEmergencyUpgrade(
_calls,
_salt,
guardiansSignatures,
securityCouncilSignatures,
zkFoundationSignature
);
vm.stopBroadcast();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

import {IProtocolUpgradeHandler} from "./IProtocolUpgradeHandler.sol";

/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IEmergencyUpgrageBoard {
function GUARDIANS() external view returns (address);

function SECURITY_COUNCIL() external view returns (address);

function ZK_FOUNDATION_SAFE() external view returns (address);

function executeEmergencyUpgrade(
IProtocolUpgradeHandler.Call[] calldata _calls,
bytes32 _salt,
bytes calldata _guardiansSignatures,
bytes calldata _securityCouncilSignatures,
bytes calldata _zkFoundationSignatures
) external;
}
9 changes: 9 additions & 0 deletions l1-contracts/deploy-scripts/interfaces/IMultisig.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IMultisig {
function members(uint256) external view returns (address);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IProtocolUpgradeHandler {
/// @dev Represents a call to be made during an upgrade.
/// @param target The address to which the call will be made.
/// @param value The amount of Ether (in wei) to be sent along with the call.
/// @param data The calldata to be executed on the `target` address.
struct Call {
address target;
uint256 value;
bytes data;
}

/// @dev Defines the structure of an upgrade that is executed by Protocol Upgrade Handler.
/// @param executor The L1 address that is authorized to perform the upgrade execution (if address(0) then anyone).
/// @param calls An array of `Call` structs, each representing a call to be made during the upgrade execution.
/// @param salt A bytes32 value used for creating unique upgrade proposal hashes.
struct UpgradeProposal {
Call[] calls;
address executor;
bytes32 salt;
}

function emergencyUpgradeBoard() external view returns (address);

function guardians() external view returns (address);

function securityCouncil() external view returns (address);
}
9 changes: 9 additions & 0 deletions l1-contracts/deploy-scripts/interfaces/ISafe.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

/// @author Matter Labs
/// @custom:security-contact [email protected]
interface ISafe {
function getMessageHash(bytes memory _message) external view returns (bytes32);
}
Loading