Commit 6c6dc18a authored by Maurelian's avatar Maurelian Committed by GitHub

Test setup results of DeployOwnership script (#10397)

* ctb: Test ownership setup scripts

* ctb: Add nested config of modules

* Add guard and module checks

* Update packages/contracts-bedrock/scripts/DeployOwnership.s.sol
Co-authored-by: default avatarMatt Solomon <matt@mattsolomon.dev>

---------
Co-authored-by: default avatarMatt Solomon <matt@mattsolomon.dev>
parent 351f6601
......@@ -24,16 +24,24 @@ struct SafeConfig {
address[] owners;
}
/// @notice Configuration for the Security Council Safe.
struct SecurityCouncilConfig {
SafeConfig safeConfig;
struct LivenessModuleConfig {
uint256 livenessInterval;
uint256 thresholdPercentage;
uint256 minOwners;
address fallbackOwner;
}
struct DeputyGuardianModuleConfig {
address deputyGuardian;
SuperchainConfig superchainConfig;
}
/// @notice Configuration for the Security Council Safe.
struct SecurityCouncilConfig {
SafeConfig safeConfig;
LivenessModuleConfig livenessModuleConfig;
DeputyGuardianModuleConfig deputyGuardianModuleConfig;
}
// The sentinel address is used to mark the start and end of the linked list of owners in the Safe.
address constant SENTINEL_OWNERS = address(0x1);
......@@ -73,12 +81,16 @@ contract DeployOwnership is Deploy {
SafeConfig memory safeConfig = SafeConfig({ threshold: 10, owners: exampleCouncilOwners });
councilConfig_ = SecurityCouncilConfig({
safeConfig: safeConfig,
livenessModuleConfig: LivenessModuleConfig({
livenessInterval: 24 weeks,
thresholdPercentage: 75,
minOwners: 8,
fallbackOwner: mustGetAddress("FoundationSafe"),
deputyGuardian: makeAddr("DeputyGuardian"),
fallbackOwner: mustGetAddress("FoundationSafe")
}),
deputyGuardianModuleConfig: DeputyGuardianModuleConfig({
deputyGuardian: mustGetAddress("FoundationSafe"),
superchainConfig: SuperchainConfig(mustGetAddress("SuperchainConfig"))
})
});
}
......@@ -109,16 +121,16 @@ contract DeployOwnership is Deploy {
function deployLivenessModule() public returns (address addr_) {
Safe councilSafe = Safe(payable(mustGetAddress("SecurityCouncilSafe")));
address guard = mustGetAddress("LivenessGuard");
SecurityCouncilConfig memory councilConfig = _getExampleCouncilConfig();
LivenessModuleConfig memory livenessModuleConfig = _getExampleCouncilConfig().livenessModuleConfig;
addr_ = address(
new LivenessModule({
_safe: councilSafe,
_livenessGuard: LivenessGuard(guard),
_livenessInterval: councilConfig.livenessInterval,
_thresholdPercentage: councilConfig.thresholdPercentage,
_minOwners: councilConfig.minOwners,
_fallbackOwner: councilConfig.fallbackOwner
_livenessInterval: livenessModuleConfig.livenessInterval,
_thresholdPercentage: livenessModuleConfig.thresholdPercentage,
_minOwners: livenessModuleConfig.minOwners,
_fallbackOwner: livenessModuleConfig.fallbackOwner
})
);
......@@ -131,11 +143,12 @@ contract DeployOwnership is Deploy {
function deployDeputyGuardianModule() public returns (address addr_) {
SecurityCouncilConfig memory councilConfig = _getExampleCouncilConfig();
Safe councilSafe = Safe(payable(mustGetAddress("SecurityCouncilSafe")));
DeputyGuardianModuleConfig memory deputyGuardianModuleConfig = councilConfig.deputyGuardianModuleConfig;
addr_ = address(
new DeputyGuardianModule({
_safe: councilSafe,
_superchainConfig: councilConfig.superchainConfig,
_deputyGuardian: councilConfig.deputyGuardian
_superchainConfig: deputyGuardianModuleConfig.superchainConfig,
_deputyGuardian: deputyGuardianModuleConfig.deputyGuardian
})
);
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import {
DeployOwnership,
SafeConfig,
SecurityCouncilConfig,
DeputyGuardianModuleConfig,
LivenessModuleConfig
} from "scripts/DeployOwnership.s.sol";
import { Test } from "forge-std/Test.sol";
import { Safe } from "safe-contracts/Safe.sol";
import { ModuleManager } from "safe-contracts/base/ModuleManager.sol";
import { GuardManager } from "safe-contracts/base/GuardManager.sol";
import { LivenessGuard } from "src/Safe/LivenessGuard.sol";
import { LivenessModule } from "src/Safe/LivenessModule.sol";
import { DeputyGuardianModule } from "src/Safe/DeputyGuardianModule.sol";
import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
contract DeployOwnershipTest is Test, DeployOwnership {
address internal constant SENTINEL_MODULES = address(0x1);
// keccak256("guard_manager.guard.address")
bytes32 internal constant GUARD_STORAGE_SLOT = 0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8;
function setUp() public override {
super.setUp();
run();
}
function _checkSafeConfig(SafeConfig memory _safeConfig, Safe _safe) internal {
assertEq(_safe.getThreshold(), _safeConfig.threshold);
address[] memory safeOwners = _safe.getOwners();
assertEq(_safeConfig.owners.length, safeOwners.length);
for (uint256 i = 0; i < safeOwners.length; i++) {
assertEq(safeOwners[i], _safeConfig.owners[i]);
}
}
function test_exampleFoundationSafe() public {
Safe foundationSafe = Safe(payable(mustGetAddress("FoundationSafe")));
SafeConfig memory exampleFoundationConfig = _getExampleFoundationConfig();
_checkSafeConfig(exampleFoundationConfig, foundationSafe);
}
function test_exampleSecurityCouncilSafe() public {
Safe securityCouncilSafe = Safe(payable(mustGetAddress("SecurityCouncilSafe")));
SecurityCouncilConfig memory exampleSecurityCouncilConfig = _getExampleCouncilConfig();
_checkSafeConfig(exampleSecurityCouncilConfig.safeConfig, securityCouncilSafe);
// Guard Checks
address livenessGuard = mustGetAddress("LivenessGuard");
// The Safe's getGuard method is internal, so we read directly from storage
// https://github.com/safe-global/safe-contracts/blob/v1.4.0/contracts/base/GuardManager.sol#L66-L72
assertEq(vm.load(address(securityCouncilSafe), GUARD_STORAGE_SLOT), bytes32(uint256(uint160(livenessGuard))));
// check that all the owners have a lastLive time in the Guard
address[] memory owners = exampleSecurityCouncilConfig.safeConfig.owners;
for (uint256 i = 0; i < owners.length; i++) {
assertEq(LivenessGuard(livenessGuard).lastLive(owners[i]), block.timestamp);
}
// Module Checks
address livenessModule = mustGetAddress("LivenessModule");
address deputyGuardianModule = mustGetAddress("DeputyGuardianModule");
(address[] memory modules, address nextModule) =
ModuleManager(securityCouncilSafe).getModulesPaginated(SENTINEL_MODULES, 3);
assertEq(modules.length, 2);
assertEq(modules[0], livenessModule);
assertEq(modules[1], deputyGuardianModule);
assertEq(nextModule, SENTINEL_MODULES); // ensures there are no more modules in the list
// DeputyGuardianModule checks
DeputyGuardianModuleConfig memory dgmConfig = exampleSecurityCouncilConfig.deputyGuardianModuleConfig;
SuperchainConfig superchainConfig = SuperchainConfig(mustGetAddress("SuperchainConfig"));
assertEq(DeputyGuardianModule(deputyGuardianModule).deputyGuardian(), dgmConfig.deputyGuardian);
assertEq(
address(DeputyGuardianModule(deputyGuardianModule).superchainConfig()), address(dgmConfig.superchainConfig)
);
// LivenessModule checks
LivenessModuleConfig memory lmConfig = exampleSecurityCouncilConfig.livenessModuleConfig;
assertEq(address(LivenessModule(livenessModule).livenessGuard()), livenessGuard);
assertEq(LivenessModule(livenessModule).livenessInterval(), lmConfig.livenessInterval);
assertEq(LivenessModule(livenessModule).thresholdPercentage(), lmConfig.thresholdPercentage);
assertEq(LivenessModule(livenessModule).minOwners(), lmConfig.minOwners);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment