Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
df2aebaf
Unverified
Commit
df2aebaf
authored
May 22, 2024
by
Maurelian
Committed by
GitHub
May 23, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ctb: Add Guardian Safe to ownership deployment (#10616)
parent
94b97363
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
88 additions
and
24 deletions
+88
-24
DeployOwnership.s.sol
packages/contracts-bedrock/scripts/DeployOwnership.s.sol
+56
-14
DeployOwnership.t.sol
packages/contracts-bedrock/test/Safe/DeployOwnership.t.sol
+32
-10
No files found.
packages/contracts-bedrock/scripts/DeployOwnership.s.sol
View file @
df2aebaf
...
@@ -32,16 +32,21 @@ struct LivenessModuleConfig {
...
@@ -32,16 +32,21 @@ struct LivenessModuleConfig {
address fallbackOwner;
address fallbackOwner;
}
}
/// @notice Configuration for the Security Council Safe.
struct SecurityCouncilConfig {
SafeConfig safeConfig;
LivenessModuleConfig livenessModuleConfig;
}
/// @notice Configuration for the Deputy Guardian Module
/// @notice Configuration for the Deputy Guardian Module
struct DeputyGuardianModuleConfig {
struct DeputyGuardianModuleConfig {
address deputyGuardian;
address deputyGuardian;
SuperchainConfig superchainConfig;
SuperchainConfig superchainConfig;
}
}
/// @notice Configuration for the
Security Council
Safe.
/// @notice Configuration for the
Guardian
Safe.
struct
SecurityCouncil
Config {
struct
Guardian
Config {
SafeConfig safeConfig;
SafeConfig safeConfig;
LivenessModuleConfig livenessModuleConfig;
DeputyGuardianModuleConfig deputyGuardianModuleConfig;
DeputyGuardianModuleConfig deputyGuardianModuleConfig;
}
}
...
@@ -62,6 +67,8 @@ contract DeployOwnership is Deploy {
...
@@ -62,6 +67,8 @@ contract DeployOwnership is Deploy {
deployFoundationSafe();
deployFoundationSafe();
deploySecurityCouncilSafe();
deploySecurityCouncilSafe();
deployGuardianSafe();
configureGuardianSafe();
configureSecurityCouncilSafe();
configureSecurityCouncilSafe();
console.log("Ownership contracts completed");
console.log("Ownership contracts completed");
...
@@ -76,6 +83,19 @@ contract DeployOwnership is Deploy {
...
@@ -76,6 +83,19 @@ contract DeployOwnership is Deploy {
safeConfig_ = SafeConfig({ threshold: 5, owners: exampleFoundationOwners });
safeConfig_ = SafeConfig({ threshold: 5, owners: exampleFoundationOwners });
}
}
/// @notice Returns a GuardianConfig similar to that of the Guardian Safe on Mainnet.
function _getExampleGuardianConfig() internal returns (GuardianConfig memory guardianConfig_) {
address[] memory exampleGuardianOwners = new address[](1);
exampleGuardianOwners[0] = mustGetAddress("SecurityCouncilSafe");
guardianConfig_ = GuardianConfig({
safeConfig: SafeConfig({ threshold: 1, owners: exampleGuardianOwners }),
deputyGuardianModuleConfig: DeputyGuardianModuleConfig({
deputyGuardian: mustGetAddress("FoundationSafe"),
superchainConfig: SuperchainConfig(mustGetAddress("SuperchainConfig"))
})
});
}
/// @notice Returns a SafeConfig similar to that of the Security Council Safe on Mainnet.
/// @notice Returns a SafeConfig similar to that of the Security Council Safe on Mainnet.
function _getExampleCouncilConfig() internal returns (SecurityCouncilConfig memory councilConfig_) {
function _getExampleCouncilConfig() internal returns (SecurityCouncilConfig memory councilConfig_) {
address[] memory exampleCouncilOwners = new address[](13);
address[] memory exampleCouncilOwners = new address[](13);
...
@@ -90,10 +110,6 @@ contract DeployOwnership is Deploy {
...
@@ -90,10 +110,6 @@ contract DeployOwnership is Deploy {
thresholdPercentage: 75,
thresholdPercentage: 75,
minOwners: 8,
minOwners: 8,
fallbackOwner: mustGetAddress("FoundationSafe")
fallbackOwner: mustGetAddress("FoundationSafe")
}),
deputyGuardianModuleConfig: DeputyGuardianModuleConfig({
deputyGuardian: mustGetAddress("FoundationSafe"),
superchainConfig: SuperchainConfig(mustGetAddress("SuperchainConfig"))
})
})
});
});
}
}
...
@@ -147,7 +163,8 @@ contract DeployOwnership is Deploy {
...
@@ -147,7 +163,8 @@ contract DeployOwnership is Deploy {
function deployDeputyGuardianModule() public returns (address addr_) {
function deployDeputyGuardianModule() public returns (address addr_) {
SecurityCouncilConfig memory councilConfig = _getExampleCouncilConfig();
SecurityCouncilConfig memory councilConfig = _getExampleCouncilConfig();
Safe councilSafe = Safe(payable(mustGetAddress("SecurityCouncilSafe")));
Safe councilSafe = Safe(payable(mustGetAddress("SecurityCouncilSafe")));
DeputyGuardianModuleConfig memory deputyGuardianModuleConfig = councilConfig.deputyGuardianModuleConfig;
DeputyGuardianModuleConfig memory deputyGuardianModuleConfig =
_getExampleGuardianConfig().deputyGuardianModuleConfig;
addr_ = address(
addr_ = address(
new DeputyGuardianModule({
new DeputyGuardianModule({
_safe: councilSafe,
_safe: councilSafe,
...
@@ -174,18 +191,43 @@ contract DeployOwnership is Deploy {
...
@@ -174,18 +191,43 @@ contract DeployOwnership is Deploy {
);
);
}
}
/// @notice Configure the Security Council Safe with the LivenessModule, DeputyGuardianModule, and LivenessGuard.
/// @notice Deploy Guardian Safe.
function configureSecurityCouncilSafe() public broadcast returns (address addr_) {
function deployGuardianSafe() public broadcast returns (address addr_) {
// Deploy and add the Deputy Guardian Module.
// Config is hardcoded here as the Guardian Safe's configuration is inflexible.
SecurityCouncilConfig memory exampleCouncilConfig = _getExampleCouncilConfig();
address[] memory owners = new address[](1);
Safe safe = Safe(mustGetAddress("SecurityCouncilSafe"));
owners[0] = mustGetAddress("SecurityCouncilSafe");
addr_ = deploySafe({ _name: "GuardianSafe", _owners: owners, _threshold: 1, _keepDeployer: true });
console.log("Deployed and configured the Guardian Safe!");
}
/// @notice Configure the Guardian Safe with the DeputyGuardianModule.
function configureGuardianSafe() public broadcast returns (address addr_) {
Safe safe = Safe(payable(mustGetAddress("GuardianSafe")));
address deputyGuardianModule = deployDeputyGuardianModule();
address deputyGuardianModule = deployDeputyGuardianModule();
_callViaSafe({
_callViaSafe({
_safe: safe,
_safe: safe,
_target: address(safe),
_target: address(safe),
_data: abi.encodeCall(ModuleManager.enableModule, (deputyGuardianModule))
_data: abi.encodeCall(ModuleManager.enableModule, (deputyGuardianModule))
});
});
console.log("DeputyGuardianModule enabled on SecurityCouncilSafe");
// Remove the deployer address (msg.sender) which was used to setup the Security Council Safe thus far
// this call is also used to update the threshold.
// Because deploySafe() always adds msg.sender first (if keepDeployer is true), we know that the previousOwner
// will be SENTINEL_OWNERS.
_callViaSafe({
_safe: safe,
_target: address(safe),
_data: abi.encodeCall(OwnerManager.removeOwner, (SENTINEL_OWNERS, msg.sender, 1))
});
console.log("DeputyGuardianModule enabled on GuardianSafe");
}
/// @notice Configure the Security Council Safe with the LivenessModule and LivenessGuard.
function configureSecurityCouncilSafe() public broadcast returns (address addr_) {
// Deploy and add the Deputy Guardian Module.
SecurityCouncilConfig memory exampleCouncilConfig = _getExampleCouncilConfig();
Safe safe = Safe(mustGetAddress("SecurityCouncilSafe"));
// Deploy and add the Liveness Guard.
// Deploy and add the Liveness Guard.
address guard = deployLivenessGuard();
address guard = deployLivenessGuard();
...
...
packages/contracts-bedrock/test/Safe/DeployOwnership.t.sol
View file @
df2aebaf
...
@@ -5,6 +5,7 @@ import {
...
@@ -5,6 +5,7 @@ import {
DeployOwnership,
DeployOwnership,
SafeConfig,
SafeConfig,
SecurityCouncilConfig,
SecurityCouncilConfig,
GuardianConfig,
DeputyGuardianModuleConfig,
DeputyGuardianModuleConfig,
LivenessModuleConfig
LivenessModuleConfig
} from "scripts/DeployOwnership.s.sol";
} from "scripts/DeployOwnership.s.sol";
...
@@ -29,6 +30,7 @@ contract DeployOwnershipTest is Test, DeployOwnership {
...
@@ -29,6 +30,7 @@ contract DeployOwnershipTest is Test, DeployOwnership {
run();
run();
}
}
/// @dev Helper function to make assertions on basic Safe config properties.
function _checkSafeConfig(SafeConfig memory _safeConfig, Safe _safe) internal view {
function _checkSafeConfig(SafeConfig memory _safeConfig, Safe _safe) internal view {
assertEq(_safe.getThreshold(), _safeConfig.threshold);
assertEq(_safe.getThreshold(), _safeConfig.threshold);
...
@@ -39,6 +41,7 @@ contract DeployOwnershipTest is Test, DeployOwnership {
...
@@ -39,6 +41,7 @@ contract DeployOwnershipTest is Test, DeployOwnership {
}
}
}
}
/// @dev Test the example Foundation Safe configuration.
function test_exampleFoundationSafe() public {
function test_exampleFoundationSafe() public {
Safe foundationSafe = Safe(payable(mustGetAddress("FoundationSafe")));
Safe foundationSafe = Safe(payable(mustGetAddress("FoundationSafe")));
SafeConfig memory exampleFoundationConfig = _getExampleFoundationConfig();
SafeConfig memory exampleFoundationConfig = _getExampleFoundationConfig();
...
@@ -46,6 +49,7 @@ contract DeployOwnershipTest is Test, DeployOwnership {
...
@@ -46,6 +49,7 @@ contract DeployOwnershipTest is Test, DeployOwnership {
_checkSafeConfig(exampleFoundationConfig, foundationSafe);
_checkSafeConfig(exampleFoundationConfig, foundationSafe);
}
}
/// @dev Test the example Security Council Safe configuration.
function test_exampleSecurityCouncilSafe() public {
function test_exampleSecurityCouncilSafe() public {
Safe securityCouncilSafe = Safe(payable(mustGetAddress("SecurityCouncilSafe")));
Safe securityCouncilSafe = Safe(payable(mustGetAddress("SecurityCouncilSafe")));
SecurityCouncilConfig memory exampleSecurityCouncilConfig = _getExampleCouncilConfig();
SecurityCouncilConfig memory exampleSecurityCouncilConfig = _getExampleCouncilConfig();
...
@@ -69,19 +73,11 @@ contract DeployOwnershipTest is Test, DeployOwnership {
...
@@ -69,19 +73,11 @@ contract DeployOwnershipTest is Test, DeployOwnership {
address livenessModule = mustGetAddress("LivenessModule");
address livenessModule = mustGetAddress("LivenessModule");
address deputyGuardianModule = mustGetAddress("DeputyGuardianModule");
address deputyGuardianModule = mustGetAddress("DeputyGuardianModule");
(address[] memory modules, address nextModule) =
(address[] memory modules, address nextModule) =
ModuleManager(securityCouncilSafe).getModulesPaginated(SENTINEL_MODULES,
3
);
ModuleManager(securityCouncilSafe).getModulesPaginated(SENTINEL_MODULES,
2
);
assertEq(modules.length,
2
);
assertEq(modules.length,
1
);
assertEq(modules[0], livenessModule);
assertEq(modules[0], livenessModule);
assertEq(modules[1], deputyGuardianModule);
assertEq(nextModule, SENTINEL_MODULES); // ensures there are no more modules in the list
assertEq(nextModule, SENTINEL_MODULES); // ensures there are no more modules in the list
// DeputyGuardianModule checks
DeputyGuardianModuleConfig memory dgmConfig = exampleSecurityCouncilConfig.deputyGuardianModuleConfig;
assertEq(DeputyGuardianModule(deputyGuardianModule).deputyGuardian(), dgmConfig.deputyGuardian);
assertEq(
address(DeputyGuardianModule(deputyGuardianModule).superchainConfig()), address(dgmConfig.superchainConfig)
);
// LivenessModule checks
// LivenessModule checks
LivenessModuleConfig memory lmConfig = exampleSecurityCouncilConfig.livenessModuleConfig;
LivenessModuleConfig memory lmConfig = exampleSecurityCouncilConfig.livenessModuleConfig;
assertEq(address(LivenessModule(livenessModule).livenessGuard()), livenessGuard);
assertEq(address(LivenessModule(livenessModule).livenessGuard()), livenessGuard);
...
@@ -92,4 +88,30 @@ contract DeployOwnershipTest is Test, DeployOwnership {
...
@@ -92,4 +88,30 @@ contract DeployOwnershipTest is Test, DeployOwnership {
// Ensure the threshold on the safe agrees with the LivenessModule's required threshold
// Ensure the threshold on the safe agrees with the LivenessModule's required threshold
assertEq(securityCouncilSafe.getThreshold(), LivenessModule(livenessModule).getRequiredThreshold(owners.length));
assertEq(securityCouncilSafe.getThreshold(), LivenessModule(livenessModule).getRequiredThreshold(owners.length));
}
}
/// @dev Test the example Guardian Safe configuration.
function test_exampleGuardianSafe() public {
Safe guardianSafe = Safe(payable(mustGetAddress("GuardianSafe")));
address[] memory owners = new address[](1);
owners[0] = mustGetAddress("SecurityCouncilSafe");
GuardianConfig memory guardianConfig = _getExampleGuardianConfig();
_checkSafeConfig(guardianConfig.safeConfig, guardianSafe);
// DeputyGuardianModule checks
address deputyGuardianModule = mustGetAddress("DeputyGuardianModule");
(address[] memory modules, address nextModule) =
ModuleManager(guardianSafe).getModulesPaginated(SENTINEL_MODULES, 2);
assertEq(modules.length, 1);
assertEq(modules[0], deputyGuardianModule);
assertEq(nextModule, SENTINEL_MODULES); // ensures there are no more modules in the list
assertEq(
DeputyGuardianModule(deputyGuardianModule).deputyGuardian(),
guardianConfig.deputyGuardianModuleConfig.deputyGuardian
);
assertEq(
address(DeputyGuardianModule(deputyGuardianModule).superchainConfig()),
address(guardianConfig.deputyGuardianModuleConfig.superchainConfig)
);
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment