Skip to content

Commit

Permalink
Merge pull request #13 from aragon/f/emergency-multisig
Browse files Browse the repository at this point in the history
Emergency multisig
  • Loading branch information
carlosgj94 authored May 15, 2024
2 parents e28e3fc + 72fe869 commit 880c8d1
Show file tree
Hide file tree
Showing 15 changed files with 3,175 additions and 1,792 deletions.
10 changes: 10 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"solidity.packageDefaultDependenciesContractsDirectory": "src",
"solidity.packageDefaultDependenciesDirectory": "lib",
"editor.formatOnSave": true,
"[solidity]": {
"editor.defaultFormatter": "NomicFoundation.hardhat-solidity"
},
"solidity.formatter": "forge",
"solidity.compileUsingRemoteVersion": "v0.8.17"
}
3 changes: 1 addition & 2 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ libs = ["lib"]
evm_version = "shanghai"
optimizer = true
optimizer-runs = 10_000_000

# solc = "0.8.20"
solc = "0.8.17"


[rpc_endpoints]
Expand Down
225 changes: 82 additions & 143 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.13;

import {VmSafe} from "forge-std/Vm.sol";
import {Script} from "forge-std/Script.sol";
import {Script, console} from "forge-std/Script.sol";
import {OptimisticTokenVotingPlugin} from "../src/OptimisticTokenVotingPlugin.sol";
import {OptimisticTokenVotingPluginSetup} from "../src/setup/OptimisticTokenVotingPluginSetup.sol";
import {MultisigPluginSetup} from "../src/setup/MultisigPluginSetup.sol";
Expand All @@ -11,8 +11,10 @@ import {GovernanceERC20} from "@aragon/osx/token/ERC20/governance/GovernanceERC2
import {GovernanceWrappedERC20} from "@aragon/osx/token/ERC20/governance/GovernanceWrappedERC20.sol";
import {PluginRepoFactory} from "@aragon/osx/framework/plugin/repo/PluginRepoFactory.sol";
import {hashHelpers, PluginSetupRef} from "@aragon/osx/framework/plugin/setup/PluginSetupProcessorHelpers.sol";
import {Addresslist} from "@aragon/osx/plugins/utils/Addresslist.sol";
import {Multisig} from "../src/Multisig.sol";
import {EmergencyMultisig} from "../src/EmergencyMultisig.sol";
import {PublicKeyRegistry} from "../src/PublicKeyRegistry.sol";
import {PluginRepo} from "@aragon/osx/framework/plugin/repo/PluginRepo.sol";
import {IPluginSetup} from "@aragon/osx/framework/plugin/setup/IPluginSetup.sol";
import {PluginSetupProcessor} from "@aragon/osx/framework/plugin/setup/PluginSetupProcessor.sol";
Expand Down Expand Up @@ -42,12 +44,8 @@ contract Deploy is Script {
daoImplementation = new DAO();

governanceERC20Base = vm.envAddress("GOVERNANCE_ERC20_BASE");
governanceWrappedERC20Base = vm.envAddress(
"GOVERNANCE_WRAPPED_ERC20_BASE"
);
pluginSetupProcessor = PluginSetupProcessor(
vm.envAddress("PLUGIN_SETUP_PROCESSOR")
);
governanceWrappedERC20Base = vm.envAddress("GOVERNANCE_WRAPPED_ERC20_BASE");
pluginSetupProcessor = PluginSetupProcessor(vm.envAddress("PLUGIN_SETUP_PROCESSOR"));
pluginRepoFactory = vm.envAddress("PLUGIN_REPO_FACTORY");
tokenAddress = vm.envAddress("TOKEN_ADDRESS");

Expand All @@ -56,9 +54,7 @@ contract Deploy is Script {
minEmergencyApprovals = uint16(vm.envUint("MIN_EMERGENCY_APPROVALS"));

stdMultisigEnsDomain = vm.envString("STD_MULTISIG_ENS_DOMAIN");
emergencyMultisigEnsDomain = vm.envString(
"EMERGENCY_MULTISIG_ENS_DOMAIN"
);
emergencyMultisigEnsDomain = vm.envString("EMERGENCY_MULTISIG_ENS_DOMAIN");

// JSON list of members
string memory root = vm.projectRoot();
Expand All @@ -72,44 +68,44 @@ contract Deploy is Script {
DAO dao = prepareDao();

// Prepare plugins
(
address p1,
PluginRepo pr1,
IPluginSetup.PreparedSetupData memory preparedSetupData1
) = prepareMultisig(dao);

(
address p2,
PluginRepo pr2,
IPluginSetup.PreparedSetupData memory preparedSetupData2
) = prepareEmergencyMultisig(dao);

(
address p3,
PluginRepo pr3,
IPluginSetup.PreparedSetupData memory preparedSetupData3
) = prepareOptimisticTokenVoting(dao, p1, p2);
(address p1, PluginRepo pr1, IPluginSetup.PreparedSetupData memory preparedSetupData1) = prepareMultisig(dao);

(address p2, PluginRepo pr2, IPluginSetup.PreparedSetupData memory preparedSetupData2) =
prepareEmergencyMultisig(dao, Addresslist(p1));

(address p3, PluginRepo pr3, IPluginSetup.PreparedSetupData memory preparedSetupData3) =
prepareOptimisticTokenVoting(dao, p1, p2);

// Apply installations
dao.grant(
address(dao),
address(pluginSetupProcessor),
dao.ROOT_PERMISSION_ID()
);
dao.grant(address(dao), address(pluginSetupProcessor), dao.ROOT_PERMISSION_ID());

applyPluginInstallation(dao, p1, pr1, preparedSetupData1);
applyPluginInstallation(dao, p2, pr2, preparedSetupData2);
applyPluginInstallation(dao, p3, pr3, preparedSetupData3);

dao.revoke(
address(dao),
address(pluginSetupProcessor),
dao.ROOT_PERMISSION_ID()
);
dao.revoke(address(dao), address(pluginSetupProcessor), dao.ROOT_PERMISSION_ID());

address publicKeyRegistry = deployPublicKeyRegistry();

// Remove ourselves as root

dao.revoke(address(dao), getDeployerWallet(), dao.ROOT_PERMISSION_ID());

// Print summary
console.log("DAO contract", address(dao));
console.log("");

console.log("Multisig plugin", p1);
console.log("Emergency multisig plugin", p2);
console.log("Optimistic token voting plugin", p3);
console.log("");

console.log("Multisig plugin repository", address(pr1));
console.log("Emergency multisig plugin repository", address(pr2));
console.log("Optimistic token voting plugin repository", address(pr3));
console.log("");

console.log("Public key registry", publicKeyRegistry);
}

// Helpers
Expand All @@ -121,20 +117,9 @@ contract Deploy is Script {
}

function getDeployerWallet() private returns (address) {
VmSafe.Wallet memory wallet = vm.createWallet(
vm.envUint("PRIVATE_KEY")
);
VmSafe.Wallet memory wallet = vm.createWallet(vm.envUint("PRIVATE_KEY"));

return
address(
uint160(
uint256(
keccak256(
abi.encode(wallet.publicKeyX, wallet.publicKeyY)
)
)
)
);
return address(uint160(uint256(keccak256(abi.encode(wallet.publicKeyX, wallet.publicKeyY)))));
}

function prepareDao() internal returns (DAO dao) {
Expand All @@ -156,24 +141,14 @@ contract Deploy is Script {
);
}

function prepareMultisig(
DAO dao
)
internal
returns (address, PluginRepo, IPluginSetup.PreparedSetupData memory)
{
function prepareMultisig(DAO dao) internal returns (address, PluginRepo, IPluginSetup.PreparedSetupData memory) {
// Deploy plugin setup
MultisigPluginSetup pluginSetup = new MultisigPluginSetup();

// Publish repo
PluginRepo pluginRepo = PluginRepoFactory(pluginRepoFactory)
.createPluginRepoWithFirstVersion(
stdMultisigEnsDomain,
address(pluginSetup),
msg.sender,
"0x",
"0x"
);
PluginRepo pluginRepo = PluginRepoFactory(pluginRepoFactory).createPluginRepoWithFirstVersion(
stdMultisigEnsDomain, address(pluginSetup), msg.sender, "0x", "0x"
);

bytes memory settingsData = pluginSetup.encodeInstallationParameters(
multisigMembers,
Expand All @@ -184,128 +159,88 @@ contract Deploy is Script {
)
);

(
address plugin,
IPluginSetup.PreparedSetupData memory preparedSetupData
) = pluginSetupProcessor.prepareInstallation(
address(dao),
PluginSetupProcessor.PrepareInstallationParams(
PluginSetupRef(
PluginRepo.Tag(1, 1),
PluginRepo(pluginRepo)
),
settingsData
)
);
(address plugin, IPluginSetup.PreparedSetupData memory preparedSetupData) = pluginSetupProcessor
.prepareInstallation(
address(dao),
PluginSetupProcessor.PrepareInstallationParams(
PluginSetupRef(PluginRepo.Tag(1, 1), PluginRepo(pluginRepo)), settingsData
)
);

return (plugin, pluginRepo, preparedSetupData);
}

function prepareEmergencyMultisig(
DAO dao
)
function prepareEmergencyMultisig(DAO dao, Addresslist multisigPlugin)
internal
returns (address, PluginRepo, IPluginSetup.PreparedSetupData memory)
{
// Deploy plugin setup
EmergencyMultisigPluginSetup pluginSetup = new EmergencyMultisigPluginSetup();

// Publish repo
PluginRepo pluginRepo = PluginRepoFactory(pluginRepoFactory)
.createPluginRepoWithFirstVersion(
emergencyMultisigEnsDomain,
address(pluginSetup),
msg.sender,
"0x",
"0x"
);
PluginRepo pluginRepo = PluginRepoFactory(pluginRepoFactory).createPluginRepoWithFirstVersion(
emergencyMultisigEnsDomain, address(pluginSetup), msg.sender, "0x", "0x"
);

bytes memory settingsData = pluginSetup.encodeInstallationParameters(
multisigMembers,
EmergencyMultisig.MultisigSettings(
true, // onlyListed
minEmergencyApprovals // minAppovals
minEmergencyApprovals, // minAppovals
Addresslist(multisigPlugin)
)
);

(
address plugin,
IPluginSetup.PreparedSetupData memory preparedSetupData
) = pluginSetupProcessor.prepareInstallation(
address(dao),
PluginSetupProcessor.PrepareInstallationParams(
PluginSetupRef(
PluginRepo.Tag(1, 1),
PluginRepo(pluginRepo)
),
settingsData
)
);
(address plugin, IPluginSetup.PreparedSetupData memory preparedSetupData) = pluginSetupProcessor
.prepareInstallation(
address(dao),
PluginSetupProcessor.PrepareInstallationParams(
PluginSetupRef(PluginRepo.Tag(1, 1), PluginRepo(pluginRepo)), settingsData
)
);

return (plugin, pluginRepo, preparedSetupData);
}

function prepareOptimisticTokenVoting(
DAO dao,
address stdProposer,
address emergencyProposer
)
function prepareOptimisticTokenVoting(DAO dao, address stdProposer, address emergencyProposer)
internal
returns (
address plugin,
PluginRepo pluginRepo,
IPluginSetup.PreparedSetupData memory preparedSetupData
)
returns (address plugin, PluginRepo pluginRepo, IPluginSetup.PreparedSetupData memory preparedSetupData)
{
// Deploy plugin setup
OptimisticTokenVotingPluginSetup pluginSetup = new OptimisticTokenVotingPluginSetup(
GovernanceERC20(governanceERC20Base),
GovernanceWrappedERC20(governanceWrappedERC20Base)
);
GovernanceERC20(governanceERC20Base), GovernanceWrappedERC20(governanceWrappedERC20Base)
);

// Publish repo
pluginRepo = PluginRepoFactory(pluginRepoFactory)
.createPluginRepoWithFirstVersion(
"ens-of-the-optimistic-token-voting",
address(pluginSetup),
msg.sender,
"0x",
"0x"
);
pluginRepo = PluginRepoFactory(pluginRepoFactory).createPluginRepoWithFirstVersion(
"ens-of-the-optimistic-token-voting", address(pluginSetup), msg.sender, "0x", "0x"
);

// Plugin settings
bytes memory settingsData;
{
OptimisticTokenVotingPlugin.OptimisticGovernanceSettings
memory votingSettings = OptimisticTokenVotingPlugin
.OptimisticGovernanceSettings(
200000, // minVetoRatio - 20%
0, // minDuration (the condition will enforce it)
0 // minProposerVotingPower
);
OptimisticTokenVotingPlugin.OptimisticGovernanceSettings memory votingSettings = OptimisticTokenVotingPlugin
.OptimisticGovernanceSettings(
200000, // minVetoRatio - 20%
0, // minDuration (the condition will enforce it)
0 // minProposerVotingPower
);

OptimisticTokenVotingPluginSetup.TokenSettings
memory tokenSettings = OptimisticTokenVotingPluginSetup
.TokenSettings(tokenAddress, "", "");
OptimisticTokenVotingPluginSetup.TokenSettings memory tokenSettings =
OptimisticTokenVotingPluginSetup.TokenSettings(tokenAddress, "", "");

GovernanceERC20.MintSettings memory mintSettings = GovernanceERC20
.MintSettings(new address[](0), new uint256[](0));
GovernanceERC20.MintSettings memory mintSettings =
GovernanceERC20.MintSettings(new address[](0), new uint256[](0));

settingsData = pluginSetup.encodeInstallationParams(
votingSettings,
tokenSettings,
mintSettings,
minStdProposalDelay,
stdProposer,
emergencyProposer
votingSettings, tokenSettings, mintSettings, minStdProposalDelay, stdProposer, emergencyProposer
);
}

(plugin, preparedSetupData) = pluginSetupProcessor.prepareInstallation(
address(dao),
PluginSetupProcessor.PrepareInstallationParams(
PluginSetupRef(PluginRepo.Tag(1, 1), PluginRepo(pluginRepo)),
settingsData
PluginSetupRef(PluginRepo.Tag(1, 1), PluginRepo(pluginRepo)), settingsData
)
);

Expand Down Expand Up @@ -337,4 +272,8 @@ contract Deploy is Script {
);
dao.execute(bytes32(uint256(0x1)), actions, 0);
}

function deployPublicKeyRegistry() internal returns (address) {
return address(new PublicKeyRegistry());
}
}
Loading

0 comments on commit 880c8d1

Please sign in to comment.