Skip to content

Commit

Permalink
Merge pull request #29 from aragon/f/clearer-setting-names
Browse files Browse the repository at this point in the history
Clearer setting names and better documentation
  • Loading branch information
brickpop authored Aug 1, 2024
2 parents 20a6273 + 6a78c32 commit 8dcbc53
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 48 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ MIN_VETO_RATIO="300000" # 30% (base 1_000_000)
L2_INACTIVITY_PERIOD="600" # in seconds (10 minutes)
L2_AGGREGATION_GRACE_PERIOD="172800" # in seconds (2 days)
SKIP_L2=true # Determines whether vote aggregation from the L2 will be disabled
MIN_STD_PROPOSAL_DELAY="8864000" # in seconds (10 days)
MIN_STD_PROPOSAL_DURATION="864000" # in seconds (10 days)
MIN_STD_APPROVALS="5" # How many multisig approvals are required
MIN_EMERGENCY_APPROVALS="10" # How many emergency multisig approvals are required

Expand Down
61 changes: 61 additions & 0 deletions DEPLOYMENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,67 @@

## Holesly

### August 1st 2024

Deployment for internal testing, with L2 voting disabled and using a pre-release voting token.

```
Chain ID: 17000
Deploying from: 0x424797Ed6d902E17b9180BFcEF452658e148e0Ab
Using production settings
Factory: 0x7B29Ab702e25fD9Ff49dceE7359a2F20679C7fAe
DAO: 0xFA90A362ef917B93c6069041f23911E6A5BAf8E6
Voting token: 0x7dbcF74e44EFc5eC635f40c962d90F2EeD81069a
Taiko Bridge: 0xA098b76a3Dd499D3F6D58D8AcCaFC8efBFd06807
Plugins
- Multisig plugin: 0xC494da7b36Bd4f6E11FE68A884571811ad7A0925
- Emergency multisig plugin: 0x48BDC52A825e285CDC615313B8614037497DbE97
- Optimistic token voting plugin: 0x8C649199ac046daD2e4a24C36f82493A4d39BE80
Plugin repositories
- Multisig plugin repository: 0x5E3Ee6a41c1185FEfFdb49F8e9930dCF6627D04f
- Emergency multisig plugin repository: 0xF7cf00690f412D4F2C2943bd7bEb7C98Ae9EE655
- Optimistic token voting plugin repository: 0x557d7502823e84629eEd562667CB000D125e7483
Helpers
- Public key registry 0x9695520e32F85eF403f6B18b8a94e44A90D5cBF0
- Delegation wall 0x15B379C5c9115e645Cdf1EF9fA03389586AfEa2A
```

### July 29th 2024

Deployment for internal testing, with L2 voting disabled and using a test voting token.

```
Chain ID: 17000
Deploying from: 0x424797Ed6d902E17b9180BFcEF452658e148e0Ab
Using internal testing settings
Minting test tokens for the multisig members and the bridge
Factory: 0xF9Be929F990F9C8bF9ed355Ddd29Af7bd9995890
DAO: 0xeB4586617089270Fe042F69Bf799590AF224807a
Voting token: 0x12b2574840dB17C2278d9725a2679E97FE266075
Taiko Bridge: 0x0000000000000000000000000000001234567890
Plugins
- Multisig plugin: 0xd8Fe1194Cf90eF38b54A110EcfeAE8F2AA5Dfe86
- Emergency multisig plugin: 0xeCBa720A8645B198b2637f6559B9155E4bc3B566
- Optimistic token voting plugin: 0xd9F6A2533efab98bA016Cb1D3001b6Ec1C246485
Plugin repositories
- Multisig plugin repository: 0xa51B2d7b7847cFB666919301e03f48b596A15871
- Emergency multisig plugin repository: 0x2ce4e91D1a00c42736730B494Ab9BFfbfEDdF2ac
- Optimistic token voting plugin repository: 0xC8f84E6E05b9C7b631A4dFD092605b8884207868
Helpers
- Public key registry 0x9695520e32F85eF403f6B18b8a94e44A90D5cBF0
- Delegation wall 0x15B379C5c9115e645Cdf1EF9fA03389586AfEa2A
```

### July 25th 2024

Deployment for internal testing, targeting test dependencies.
Expand Down
126 changes: 84 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@ This reposity contains the codebase of the Taiko DAO, along with its 3 plugins a

The DAO contract is an [Aragon DAO](https://github.com/aragon/osx), on which an **Optimistic Token Voting plugin** has the permission to execute proposals. Proposals on this plugin can only be created by two distinct multisig plugins, belonging to Taiko's Security Council.

The Security Council has a standard multisig plugin and an emergency variant. The former one is intended to be used most of the time, if not always. A certain majority of Security Council members need to approve it for it to make it to the community vote. The latter, is meant to only be used in exceptional situations, i.e. when a security vulnerability needs to be addressed immediately.
![Taiko DAO Overview](./img/overview.png)

The Security Council operates a standard multisig plugin and an emergency variant. The standard Multisig is designed to be the place where DAO proposals start their journey. Any signer can submit a new proposal to the Security Council. After a certain approval ratio is reached, the proposal will be forwarded to the Optimistic voting plugin, where the community will need to ratify it.

The Emergency Multisig, is meant to only be used under exceptional circumstances, i.e. when a critical vulnerability needs to be addressed immediately. Any signer can submit proposals as well, but these proposals will need to be approved by a super majority before they can be executed directly on the DAO.

Another key difference is that the Emergency Multisig is designed such in a way that the human readable description and the actions are private to the signers until the proposal is finally executed.

[Learn more about Aragon OSx](#protocol-overview).

See [Deploying the DAO](#deploying-the-dao) below and check out the [latest deployments](./DEPLOYMENTS.md).
See [Deploying the DAO](#deploying-the-dao) below and check out the [contract deployments](./DEPLOYMENTS.md).

## Optimistic Token Voting plugin

This plugin is an adapted version of Aragon's [Optimistic Token Voting plugin](https://github.com/aragon/optimistic-token-voting-plugin).

Only addresses that have been granted `PROPOSER_PERMISSION_ID` on the plugin can create proposals. These adresses belong to the two multisig's belonging to the Security Council.
Only addresses that have been granted `PROPOSER_PERMISSION_ID` on the plugin can create proposals. These adresses belong to the two multisig's governed by the Security Council.

Proposals can only be executed when a certain amount of vetoes hasn't emerged after a given period of time.
Proposals can only be executed when the veto threshold hasn't been reached after a given period of time.

The governance settings need to be defined when the plugin is installed but the DAO can update them at any time.

Expand All @@ -27,53 +33,87 @@ The governance settings need to be defined when the plugin is installed but the
- The DAO can update the plugin settings
- The DAO can upgrade the plugin

## Multisig (standard)
## Multisig (standard flow)

It allows the Security Council members to create and approve proposals. After a certain minimum of approvals is met, proposals can be relayed to the [Optimistic Token Voting plugin](#optimistic-token-voting-plugin) only.

Implements a list of addresses, where proposals can only be relayed to the [Optimistic Token Voting plugin](#optimistic-token-voting-plugin) after being approved.
The ability to relay proposals to the [Optimistic Token Voting plugin](#optimistic-token-voting-plugin) is restricted by a [permission condition](src/conditions/StandardProposalCondition.sol), which ensures that a minimum veto period is defined as part of the parameters.

![Standard proposal flow](./img/std-proposal-flow.png)

### Permissions

- Only members can create proposals
- Only members can approve
- The plugin can only create proposals on the [Optimistic Token Voting plugin](#optimistic-token-voting-plugin) provided that the `duration` is equal or greater than the minimum defined
- The DAO can update the plugin settings

## Emergency Multisig

Same as before, it implements a list of addresses, where proposals can only be relayed to the [Optimistic Token Voting plugin](#optimistic-token-voting-plugin) after being approved.
Like before, this plugin allows Security Council members to create and approve proposals. If a super majority approves, proposals can be relayed to the [Optimistic Token Voting plugin](#optimistic-token-voting-plugin) with a delay period of potentially 0. This is, being executed immediately.

The address list of this plugin is taken from the standard Multisig plugin. Any changes on the former will effect both plugin instances.

There are two key differences with the standard Multisig:
1. The proposal's metadata and the actions to execute are encrypted, only the Security Council members have the means to decrypt them
2. When the proposal is executed, the metadata and the actions become publicly visible on the [Optimistic Token Voting plugin](#optimistic-token-voting-plugin). There is an integrity check to prevent any changes to the originally approved content.

There are two key differences:
1. The proposal's metadata and the actions to execute are encrypted, only available to the Security Council members
2. When approved by a super majority, the proposal can be executed on the DAO immediately, going through the [Optimistic Token Voting plugin](#optimistic-token-voting-plugin).
![Emergency proposal flow](./img/emergency-proposal-flow.png)

## Plugin Installation
### Permissions

The Emergency Multisig settings are the same as for the standard Multisig.

- Only members can create proposals
- Only members can approve
- The plugin can only create proposals on the [Optimistic Token Voting plugin](#optimistic-token-voting-plugin) provided that the `duration` is equal or greater than the minimum defined
- The DAO can update the plugin settings

## Public Key Registry

This is a helper contract that allows Security Council members to register the public key of their deterministic ephemeral wallet. The available public keys will be used to encrypt the proposal metadata and actions. Refer to the UI repository for the encryption details.

NOTE: A published public key cannot be changed once published.

- A wallet can only generate one derived key pair.
- Public key registration is an automated process. No human error should be possible.
- Altering an encryption key is a strange edge case of which the rest of signers should be aware of.

## Delegation Wall

This is a very simple contract that serves the purpose of storing the IPFS URI's pointing to the delegation profile posted by all candidates. Profiles can be updated by the owner and read by everyone.

## Installing plugins to the DAO

### Installing the initial set of plugins on the DAO

This is taken care by the `TaikoDAOFactory` contract. Is is invoked by `scripts/Deploy.s.sol` and it creates an immutable DAO deployment, given a certain settings. To create a DAO with different settings, a new factory needs to be deployed.
This is taken care by the [TaikoDAOFactory](src/factory/TaikoDaoFactory.sol) contract. It is invoked by [scripts/Deploy.s.sol](script/Deploy.s.sol) and it creates a holistic, immutable DAO deployment, given some settings. To create a new DAO with new settings, a new factory needs to be deployed.

### Installing plugins on the existing DAO

Plugin changes need a proposal to be passed when the DAO already exists.

There are two steps, a permissionless **preparation** and a privileged **application**.

1. Calling `pluginSetupProcessor.prepareInstallation()`
- A new plugin instance is deployed with the desired settings
- The call requests a set of permissions to be applied by the DAO
2. Editors pass a proposal to make the DAO call `applyInstallation()` on the [PluginSetupProcessor](https://devs.aragon.org/docs/osx/how-it-works/framework/plugin-management/plugin-setup/)
- The call stores the request of a set of permissions
2. A proposal is passed to make the DAO call `applyInstallation()` on the [PluginSetupProcessor](https://devs.aragon.org/docs/osx/how-it-works/framework/plugin-management/plugin-setup/)
- This applies the requested permissions and the plugin becomes installed

See `OptimisticTokenVotingPluginSetup`.
See [OptimisticTokenVotingPluginSetup](src/setup/OptimisticTokenVotingPluginSetup.sol).

[Learn more about plugin setup's](https://devs.aragon.org/docs/osx/how-it-works/framework/plugin-management/plugin-setup/) and [preparing installations](https://devs.aragon.org/docs/sdk/examples/client/prepare-installation).

## OSx protocol overview

OSx [DAO's](https://github.com/aragon/osx/blob/develop/packages/contracts/src/core/dao/DAO.sol) are designed to hold all the assets and rights by themselves, while plugins are custom, opt-in pieces of logic that can perform any type of actions governed by the DAO's permission database.
OSx [DAO's](https://github.com/aragon/osx/blob/develop/packages/contracts/src/core/dao/DAO.sol) are designed to hold all the assets and rights by themselves. On the other hand, plugins are custom opt-in pieces of logic that can implement any type of governance. They are meant to eventually make the DAO execute a certain set of actions.

The DAO contract can be deployed by using Aragon's `DAOFactory` contract. This will deploy a new DAO with the desired plugins and settings.
The whole ecosystem is governed by the DAO's permission database, which is used to restrict actions to only the role holding the appropriate permission.

### How permissions work

An Aragon DAO is a set of permissions that are used to restrict who can do what and where.
An Aragon DAO is a set of permissions that are used to define who can do what, and where.

A permission looks like:

Expand All @@ -91,7 +131,7 @@ function revoke(address _where, address _who, bytes32 _permissionId);

### Permission Conditions

For the cases where an unrestricted permission is not derisable, a [Permission Condition](https://devs.aragon.org/docs/osx/how-it-works/core/permissions/conditions) can be used.
For the cases where an unrestricted permission is not derisable, a [Permission Condition](https://devs.aragon.org/osx/how-it-works/core/permissions/conditions) can be used.

Conditional permissions look like this:

Expand All @@ -110,7 +150,7 @@ function grantWithCondition(

See the condition contract boilerplate. It provides the plumbing to easily restrict what the different multisig plugins can propose on the OptimisticVotingPlugin.

[Learn more about OSx permissions](https://devs.aragon.org/docs/osx/how-it-works/core/permissions/)
[Learn more about OSx permissions](https://devs.aragon.org/osx/how-it-works/core/permissions/#permissions)

### Permissions being used

Expand Down Expand Up @@ -149,7 +189,7 @@ To this end, the DAO has a struct called `Action { to, value, data }`, which wil
- Ensure that there is at least always one plugin with `EXECUTE_PERMISSION` on the DAO
- Ensure that the DAO is ROOT on itself
- Use the `_gap[]` variable for upgradeable plugins, as a way to reserve storage slots for future plugin implementations
- Decrement the `_gap` number for every new variable you add in the future
- Decrement the `_gap` number for every new variable (slot) you add in the future

### Plugin upgradeability

Expand All @@ -173,51 +213,53 @@ $ forge build
$ forge test
```

### Deploying the DAO

1. Edit `script/multisig-members.json` with the list of addresses to set as signers
2. Run `forge build`
3. Copy `.env.example` into `.env` and define the settings
4. Run `source .env` to load them
5. Set the RPC URL and run the deployment script
### Formatting the code

```shell
RPC_URL="https://eth-holesky.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify --via-ir
$ forge fmt
```

If you get the error `Failed to get EIP-1559 fees`, add `--legacy` to the last command:
### Gas Snapshots

```shell
forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify --via-ir --legacy
$ forge snapshot
```

If a some contracts fail to verify on Etherscan, retry with this command:
### Run a local test EVM

```shell
forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --verify --via-ir --legacy --private-key "$DEPLOYMENT_PRIVATE_KEY" --resume
$ anvil
```

### Formatting the code
### Cast

```shell
$ forge fmt
$ cast <subcommand>
```

### Gas Snapshots
## Deployment

### Deploying the DAO

1. Edit `script/multisig-members.json` with the list of addresses to set as signers
2. Run `forge build && forge test`
3. Copy `.env.example` into `.env` and define the settings
4. Run `source .env` to load them
5. Set the RPC URL and run the deployment script

```shell
$ forge snapshot
RPC_URL="https://eth-holesky.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify
```

### Run a local test EVM
If you get the error `Failed to get EIP-1559 fees`, add `--legacy` to the last command:

```shell
$ anvil
forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify --legacy
```

### Cast
If a some contracts fail to verify on Etherscan, retry with this command:

```shell
$ cast <subcommand>
forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --verify --legacy --private-key "$DEPLOYMENT_PRIVATE_KEY" --resume
```
Binary file added img/emergency-proposal-flow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/std-proposal-flow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ contract Deploy is Script {
skipL2: bool(vm.envBool("SKIP_L2")),
// Voting settings
minVetoRatio: uint32(vm.envUint("MIN_VETO_RATIO")),
minStdProposalDelay: uint64(vm.envUint("MIN_STD_PROPOSAL_DELAY")),
minStdProposalDuration: uint64(vm.envUint("MIN_STD_PROPOSAL_DURATION")),
minStdApprovals: uint16(vm.envUint("MIN_STD_APPROVALS")),
minEmergencyApprovals: uint16(vm.envUint("MIN_EMERGENCY_APPROVALS")),
// OSx contracts
Expand Down Expand Up @@ -131,7 +131,7 @@ contract Deploy is Script {
skipL2: bool(vm.envBool("SKIP_L2")),
// Voting settings
minVetoRatio: uint32(vm.envUint("MIN_VETO_RATIO")),
minStdProposalDelay: uint64(vm.envUint("MIN_STD_PROPOSAL_DELAY")),
minStdProposalDuration: uint64(vm.envUint("MIN_STD_PROPOSAL_DURATION")),
minStdApprovals: uint16(vm.envUint("MIN_STD_APPROVALS")),
minEmergencyApprovals: uint16(vm.envUint("MIN_EMERGENCY_APPROVALS")),
// OSx contracts
Expand Down
6 changes: 3 additions & 3 deletions src/factory/TaikoDaoFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ contract TaikoDaoFactory {
bool skipL2;
// Voting settings
uint32 minVetoRatio;
uint64 minStdProposalDelay;
uint64 minStdProposalDuration;
uint16 minStdApprovals;
uint16 minEmergencyApprovals;
// OSx contracts
Expand Down Expand Up @@ -162,7 +162,7 @@ contract TaikoDaoFactory {
Multisig.MultisigSettings(
true, // onlyListed
settings.minStdApprovals,
settings.minStdProposalDelay // destination minDuration
settings.minStdProposalDuration // destination minDuration
)
);

Expand Down Expand Up @@ -244,7 +244,7 @@ contract TaikoDaoFactory {
unusedMintSettings,
settings.taikoL1ContractAddress,
settings.taikoBridgeAddress,
settings.minStdProposalDelay,
settings.minStdProposalDuration,
stdProposer,
emergencyProposer
)
Expand Down

0 comments on commit 8dcbc53

Please sign in to comment.