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
Hide 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 {
address fallbackOwner;
}
/// @notice Configuration for the Security Council Safe.
struct SecurityCouncilConfig {
SafeConfig safeConfig;
LivenessModuleConfig livenessModuleConfig;
}
/// @notice Configuration for the Deputy Guardian Module
struct DeputyGuardianModuleConfig {
address deputyGuardian;
SuperchainConfig superchainConfig;
}
/// @notice Configuration for the
Security Council
Safe.
struct
SecurityCouncil
Config {
/// @notice Configuration for the
Guardian
Safe.
struct
Guardian
Config {
SafeConfig safeConfig;
LivenessModuleConfig livenessModuleConfig;
DeputyGuardianModuleConfig deputyGuardianModuleConfig;
}
...
...
@@ -62,6 +67,8 @@ contract DeployOwnership is Deploy {
deployFoundationSafe();
deploySecurityCouncilSafe();
deployGuardianSafe();
configureGuardianSafe();
configureSecurityCouncilSafe();
console.log("Ownership contracts completed");
...
...
@@ -76,6 +83,19 @@ contract DeployOwnership is Deploy {
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.
function _getExampleCouncilConfig() internal returns (SecurityCouncilConfig memory councilConfig_) {
address[] memory exampleCouncilOwners = new address[](13);
...
...
@@ -90,10 +110,6 @@ contract DeployOwnership is Deploy {
thresholdPercentage: 75,
minOwners: 8,
fallbackOwner: mustGetAddress("FoundationSafe")
}),
deputyGuardianModuleConfig: DeputyGuardianModuleConfig({
deputyGuardian: mustGetAddress("FoundationSafe"),
superchainConfig: SuperchainConfig(mustGetAddress("SuperchainConfig"))
})
});
}
...
...
@@ -147,7 +163,8 @@ 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;
DeputyGuardianModuleConfig memory deputyGuardianModuleConfig =
_getExampleGuardianConfig().deputyGuardianModuleConfig;
addr_ = address(
new DeputyGuardianModule({
_safe: councilSafe,
...
...
@@ -174,18 +191,43 @@ contract DeployOwnership is Deploy {
);
}
/// @notice Configure the Security Council Safe with the LivenessModule, DeputyGuardianModule, 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"));
/// @notice Deploy Guardian Safe.
function deployGuardianSafe() public broadcast returns (address addr_) {
// Config is hardcoded here as the Guardian Safe's configuration is inflexible.
address[] memory owners = new address[](1);
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();
_callViaSafe({
_safe: safe,
_target: address(safe),
_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.
address guard = deployLivenessGuard();
...
...
packages/contracts-bedrock/test/Safe/DeployOwnership.t.sol
View file @
df2aebaf
...
...
@@ -5,6 +5,7 @@ import {
DeployOwnership,
SafeConfig,
SecurityCouncilConfig,
GuardianConfig,
DeputyGuardianModuleConfig,
LivenessModuleConfig
} from "scripts/DeployOwnership.s.sol";
...
...
@@ -29,6 +30,7 @@ contract DeployOwnershipTest is Test, DeployOwnership {
run();
}
/// @dev Helper function to make assertions on basic Safe config properties.
function _checkSafeConfig(SafeConfig memory _safeConfig, Safe _safe) internal view {
assertEq(_safe.getThreshold(), _safeConfig.threshold);
...
...
@@ -39,6 +41,7 @@ contract DeployOwnershipTest is Test, DeployOwnership {
}
}
/// @dev Test the example Foundation Safe configuration.
function test_exampleFoundationSafe() public {
Safe foundationSafe = Safe(payable(mustGetAddress("FoundationSafe")));
SafeConfig memory exampleFoundationConfig = _getExampleFoundationConfig();
...
...
@@ -46,6 +49,7 @@ contract DeployOwnershipTest is Test, DeployOwnership {
_checkSafeConfig(exampleFoundationConfig, foundationSafe);
}
/// @dev Test the example Security Council Safe configuration.
function test_exampleSecurityCouncilSafe() public {
Safe securityCouncilSafe = Safe(payable(mustGetAddress("SecurityCouncilSafe")));
SecurityCouncilConfig memory exampleSecurityCouncilConfig = _getExampleCouncilConfig();
...
...
@@ -69,19 +73,11 @@ contract DeployOwnershipTest is Test, DeployOwnership {
address livenessModule = mustGetAddress("LivenessModule");
address deputyGuardianModule = mustGetAddress("DeputyGuardianModule");
(address[] memory modules, address nextModule) =
ModuleManager(securityCouncilSafe).getModulesPaginated(SENTINEL_MODULES,
3
);
assertEq(modules.length,
2
);
ModuleManager(securityCouncilSafe).getModulesPaginated(SENTINEL_MODULES,
2
);
assertEq(modules.length,
1
);
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;
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);
...
...
@@ -92,4 +88,30 @@ contract DeployOwnershipTest is Test, DeployOwnership {
// Ensure the threshold on the safe agrees with the LivenessModule's required threshold
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