Skip to content

Commit

Permalink
Almost ready
Browse files Browse the repository at this point in the history
  • Loading branch information
brickpop committed Sep 25, 2024
1 parent 941a788 commit 4083b5c
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 50 deletions.
3 changes: 0 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ DEPLOY_AS_PRODUCTION=true
MULTISIG_MEMBERS_JSON_FILE_NAME="/script/multisig-members.json"

# MULTISIG PARAMETERS
MIN_PROPOSAL_DURATION="864000" # in seconds (10 days)
MIN_APPROVALS="5" # How many multisig approvals are required
MULTISIG_PROPOSAL_EXPIRATION_PERIOD="864000" # How long until a pending proposal expires (10 days)

Expand Down Expand Up @@ -51,5 +50,3 @@ SIMPLE_GAUGE_VOTER_REPO_ENS_SUBDOMAIN="my-simple-gauge-voter-0"
DAO_FACTORY="0xE640Da5AD169630555A86D9b6b9C145B4961b1EB"
PLUGIN_SETUP_PROCESSOR="0xCe0B4124dea6105bfB85fB4461c4D39f360E9ef3"
PLUGIN_REPO_FACTORY="0x95D563382BeD5AcB458759EE05b27DF2CB019Cc7"

# GOVERNANCE_ERC20_BASE="0xC24188a73dc09aA7C721f96Ad8857B469C01dC9f"
84 changes: 58 additions & 26 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import {VotingEscrow, Clock, Lock, QuadraticIncreasingEscrow, ExitQueue, SimpleG
import {PluginRepo} from "@aragon/osx/framework/plugin/repo/PluginRepo.sol";
import {PluginRepoFactory} from "@aragon/osx/framework/plugin/repo/PluginRepoFactory.sol";
import {PluginSetupProcessor} from "@aragon/osx/framework/plugin/setup/PluginSetupProcessor.sol";
import {MockERC20} from "@mocks/MockERC20.sol";

contract Deploy is Script {
SimpleGaugeVoterSetup simpleGaugeVoterSetup;

/// @dev Thrown when attempting to create a DAO with an empty multisig
/// @dev Thrown when attempting to deploy a multisig with no members
error EmptyMultisig();

modifier broadcast() {
Expand All @@ -26,18 +27,11 @@ contract Deploy is Script {
vm.stopBroadcast();
}

/// @notice Runs the deployment flow, records the given parameters and artifacts, and it becomes read only
function run() public broadcast {
// NOTE:
// Deploying the plugin setup's separately because of the code size limit

// Note: Multisig is already deployed, not redeploying

// Deploy the voter plugin setup
// TODO:

DeploymentParameters memory parameters = getDeploymentParameters(
vm.envBool("DEPLOY_AS_PRODUCTION")
);
// Prepare all parameters
bool isProduction = vm.envBool("DEPLOY_AS_PRODUCTION");
DeploymentParameters memory parameters = getDeploymentParameters(isProduction);

// Create the DAO
GaugesDaoFactory factory = new GaugesDaoFactory(parameters);
Expand All @@ -50,13 +44,20 @@ contract Deploy is Script {
function getDeploymentParameters(
bool isProduction
) internal returns (DeploymentParameters memory parameters) {
address[] memory multisigMembers = readMultisigMembers();
TokenParameters[] memory tokenParameters = getTokenParameters(isProduction);

// NOTE: Multisig is already deployed, using the existing Aragon's repo
// NOTE: Deploying the plugin setup from the current script to avoid code size constraints

SimpleGaugeVoterSetup gaugeVoterPluginSetup = deploySimpleGaugeVoterPluginSetup();

parameters = DeploymentParameters({
// Multisig settings
minProposalDuration: uint64(vm.envUint("MIN_PROPOSAL_DURATION")),
minApprovals: uint8(vm.envUint("MIN_APPROVALS")),
multisigMembers: readMultisigMembers(),
multisigMembers: multisigMembers,
// Gauge Voter
tokenParameters: getTokenParameters(isProduction),
tokenParameters: tokenParameters,
feePercent: vm.envUint("FEE_PERCENT_WEI"),
warmupPeriod: uint64(vm.envUint("WARMUP_PERIOD")),
cooldownPeriod: uint64(vm.envUint("COOLDOWN_PERIOD")),
Expand All @@ -67,7 +68,7 @@ contract Deploy is Script {
multisigPluginRelease: uint8(vm.envUint("MULTISIG_PLUGIN_RELEASE")),
multisigPluginBuild: uint16(vm.envUint("MULTISIG_PLUGIN_BUILD")),
// Voter plugin setup and ENS
voterPluginSetup: deploySimpleGaugeVoterPluginSetup(),
voterPluginSetup: gaugeVoterPluginSetup,
voterEnsSubdomain: vm.envString("SIMPLE_GAUGE_VOTER_REPO_ENS_SUBDOMAIN"),
// OSx addresses
osxDaoFactory: vm.envAddress("DAO_FACTORY"),
Expand Down Expand Up @@ -99,7 +100,7 @@ contract Deploy is Script {

function getTokenParameters(
bool isProduction
) internal view returns (TokenParameters[] memory tokenParameters) {
) internal returns (TokenParameters[] memory tokenParameters) {
if (isProduction) {
// USE TOKEN(s)
console.log("Using production parameters");
Expand All @@ -122,15 +123,39 @@ contract Deploy is Script {
}
} else {
// MINT TEST TOKEN
console.log("Using testing parameters (minting 2 token)");
console.log("Using testing parameters (minting 2 test tokens)");

address[] memory multisigMembers = readMultisigMembers();
address[] memory tokens = new address[](2);
tokens[0] = createTestToken(multisigMembers);
tokens[1] = createTestToken(multisigMembers);

// TODO:
tokenParameters = new TokenParameters[](2);
tokenParameters[0] = TokenParameters({
token: tokens[0],
veTokenName: "VE Token 1",
veTokenSymbol: "veTK1"
});
tokenParameters[1] = TokenParameters({
token: tokens[1],
veTokenName: "VE Token 2",
veTokenSymbol: "veTK2"
});
}
}

function createTestToken(address[] memory holders) internal {
// TODO:
address newToken = vm.envAddress("GOVERNANCE_ERC20_BASE");
function createTestToken(address[] memory holders) internal returns (address) {
MockERC20 newToken = new MockERC20();

for (uint i = 0; i < holders.length; ) {
newToken.mint(holders[i], 50 ether);

unchecked {
i++;
}
}

return address(newToken);
}

function printDeploymentSummary(GaugesDaoFactory factory) internal view {
Expand All @@ -147,9 +172,16 @@ contract Deploy is Script {
console.log("Plugins");
console.log("- Multisig plugin:", address(deployment.multisigPlugin));
console.log("");
for (uint i = 0; i < deployment.voterPlugins.length; ) {
console.log("- Token:", address(deploymentParameters.tokenParameters[i].token));
console.log(" Gauge voter plugin:", address(deployment.voterPlugins[i]));

for (uint i = 0; i < deployment.gaugePluginSets.length; ) {
console.log("- Using token:", address(deploymentParameters.tokenParameters[i].token));
console.log(" Gauge voter plugin:", address(deployment.gaugePluginSets[i].plugin));
console.log(" Curve:", address(deployment.gaugePluginSets[i].curve));
console.log(" Exit Queue:", address(deployment.gaugePluginSets[i].exitQueue));
console.log(" Voting Escrow:", address(deployment.gaugePluginSets[i].votingEscrow));
console.log(" Clock:", address(deployment.gaugePluginSets[i].clock));
console.log(" NFT Lock:", address(deployment.gaugePluginSets[i].nftLock));

unchecked {
i++;
}
Expand All @@ -158,7 +190,7 @@ contract Deploy is Script {

console.log("Plugin repositories");
console.log(
"- Eultisig plugin repository (existing):",
"- Multisig plugin repository (existing):",
address(deploymentParameters.multisigPluginRepo)
);
console.log("- Gauge voter plugin repository:", address(deployment.voterPluginRepo));
Expand Down
66 changes: 45 additions & 21 deletions src/factory/GaugesDaoFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {Clock} from "@clock/Clock.sol";
import {IEscrowCurveUserStorage} from "@escrow-interfaces/IEscrowCurveIncreasing.sol";
import {IWithdrawalQueueErrors} from "src/escrow/increasing/interfaces/IVotingEscrowIncreasing.sol";
import {IGaugeVote} from "src/voting/ISimpleGaugeVoter.sol";
import {SimpleGaugeVoter, SimpleGaugeVoterSetup, ISimpleGaugeVoterSetupParams} from "src/voting/SimpleGaugeVoterSetup.sol";
import {VotingEscrow, Clock, Lock, QuadraticIncreasingEscrow, ExitQueue, SimpleGaugeVoter, SimpleGaugeVoterSetup, ISimpleGaugeVoterSetupParams} from "src/voting/SimpleGaugeVoterSetup.sol";
import {Addresslist} from "@aragon/osx/plugins/utils/Addresslist.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {PluginSetupProcessor} from "@aragon/osx/framework/plugin/setup/PluginSetupProcessor.sol";
Expand All @@ -23,22 +23,24 @@ import {createERC1967Proxy} from "@aragon/osx/utils/Proxy.sol";
import {PermissionLib} from "@aragon/osx/core/permission/PermissionLib.sol";

/// @notice The struct containing all the parameters to deploy the DAO
/// @param token1Address The address of the IVotes compatible ERC20 token contract to use for the voting power
/// @param token2Address The address of the IVotes compatible ERC20 token contract to use for the voting power
/// @param minApprovals The amount of approvals required for the multisig to be able to execute a proposal on the DAO
// OSx
/// @param multisigMembers The list of addresses to be defined as the initial multisig signers
/// @param tokenParameters A list with the tokens and metadata for which a plugin and a VE should be deployed
/// @param feePercent The fee taken on withdrawals (1 ether = 100%)
/// @param warmupPeriod Delay in seconds after depositing before voting becomes possible
/// @param cooldownPeriod Delay seconds after queuing an exit before withdrawing becomes possible
/// @param minLockDuration Min seconds a user must have locked in escrow before they can queue an exit
/// @param votingPaused Prevent voting until manually activated by the multisig
/// @param multisigPluginRepo Address of Aragon's multisig plugin repository on the given network
/// @param multisigPluginRelease The release of the multisig plugin to target
/// @param multisigPluginBuild The build of the multisig plugin to target
/// @param voterPluginSetup The address of the Gauges Voter plugin setup contract to create a repository with
/// @param voterEnsSubdomain The ENS subdomain under which the plugin reposiroty will be created
/// @param osxDaoFactory The address of the OSx DAO factory contract, used to retrieve the DAO implementation address
/// @param pluginSetupProcessor The address of the OSx PluginSetupProcessor contract on the target chain
/// @param pluginRepoFactory The address of the OSx PluginRepoFactory contract on the target chain
// Plugins
/// @param multisigPluginSetup The address of the already deployed plugin setup for the standard multisig
/// @param votingPluginSetup The address of the already deployed plugin setup for the optimistic voting plugin
/// @param multisigMembers The list of addresses to be defined as the initial multisig signers
/// @param multisigEnsDomain The subdomain to use as the ENS for the standard mulsitig plugin setup. Note: it must be unique and available.
/// @param votingEnsDomain The subdomain to use as the ENS for the optimistic voting plugin setup. Note: it must be unique and available.
struct DeploymentParameters {
// Multisig settings
uint64 minProposalDuration;
uint16 minApprovals;
address[] multisigMembers;
// Gauge Voter
Expand Down Expand Up @@ -66,15 +68,27 @@ struct TokenParameters {
string veTokenSymbol;
}

/// @notice Struct containing the plugin and all of its helpers
struct GaugePluginSet {
SimpleGaugeVoter plugin;
QuadraticIncreasingEscrow curve;
ExitQueue exitQueue;
VotingEscrow votingEscrow;
Clock clock;
Lock nftLock;
}

/// @notice Contains the artifacts that resulted from running a deployment
struct Deployment {
DAO dao;
// Plugins
Multisig multisigPlugin;
SimpleGaugeVoter[] voterPlugins;
GaugePluginSet[] gaugePluginSets;
// Plugin repo's
PluginRepo voterPluginRepo;
}

/// @notice A singleton contract designed to run the deployment once and become a read-only store of the contracts deployed
contract GaugesDaoFactory {
/// @notice Thrown when attempting to call deployOnce() when the DAO is already deployed.
error AlreadyDeployed();
Expand All @@ -88,6 +102,7 @@ contract GaugesDaoFactory {
parameters = _parameters;
}

/// @notice Run the deployment and store the artifacts in a read-only store that can be retrieved via `getDeployment()` and `getDeploymentParameters()`
function deployOnce() public {
if (address(deployment.dao) != address(0)) revert AlreadyDeployed();

Expand Down Expand Up @@ -122,29 +137,27 @@ contract GaugesDaoFactory {
// GAUGE VOTER(s)
{
IPluginSetup.PreparedSetupData memory preparedVoterSetupData;
SimpleGaugeVoter voterPlugin;

PluginRepo.Tag memory repoTag = PluginRepo.Tag(1, 1);

deployment.voterPlugins = new SimpleGaugeVoter[](parameters.tokenParameters.length);
GaugePluginSet memory pluginSet;

for (uint i = 0; i < parameters.tokenParameters.length; ) {
(
voterPlugin,
pluginSet,
deployment.voterPluginRepo,
preparedVoterSetupData
) = prepareSimpleGaugeVoterPlugin(dao, parameters.tokenParameters[i], repoTag);

deployment.gaugePluginSets.push(pluginSet);

applyPluginInstallation(
dao,
address(voterPlugin),
address(pluginSet.plugin),
deployment.voterPluginRepo,
repoTag,
preparedVoterSetupData
);

deployment.voterPlugins[i] = voterPlugin;

unchecked {
i++;
}
Expand Down Expand Up @@ -229,7 +242,7 @@ contract GaugesDaoFactory {
DAO dao,
TokenParameters memory tokenParameters,
PluginRepo.Tag memory repoTag
) internal returns (SimpleGaugeVoter, PluginRepo, IPluginSetup.PreparedSetupData memory) {
) internal returns (GaugePluginSet memory, PluginRepo, IPluginSetup.PreparedSetupData memory) {
// Publish repo
PluginRepo pluginRepo = PluginRepoFactory(parameters.pluginRepoFactory)
.createPluginRepoWithFirstVersion(
Expand Down Expand Up @@ -263,7 +276,18 @@ contract GaugesDaoFactory {
settingsData
)
);
return (SimpleGaugeVoter(plugin), pluginRepo, preparedSetupData);

address[] memory helpers = preparedSetupData.helpers;
GaugePluginSet memory pluginSet = GaugePluginSet({
plugin: SimpleGaugeVoter(plugin),
curve: QuadraticIncreasingEscrow(helpers[0]),
exitQueue: ExitQueue(helpers[1]),
votingEscrow: VotingEscrow(helpers[2]),
clock: Clock(helpers[3]),
nftLock: Lock(helpers[4])
});

return (pluginSet, pluginRepo, preparedSetupData);
}

function applyPluginInstallation(
Expand Down

0 comments on commit 4083b5c

Please sign in to comment.