Skip to content

A library of OSx conditions designed to provide fine grained control on granted permissions

Notifications You must be signed in to change notification settings

aragon/conditions

Repository files navigation

OSx Condition Library

This reposity contains a library of OSx conditions, meant to be used by any DAO wishing to guard contract functions by using common permission patterns.

Overview

  • Execute Selector Condition: only allows a predefined set of function selectors to be invoked via execute()
  • Selector Condition: only allows a predefined set of function selectors to be invoked directly

Learn more about Aragon OSx.

Get Started

See the deployments available on each network on DEPLOYMENTS.md

Build

To get started, ensure that Foundry and Make are installed on your computer.

Using the Makefile

The Makefile is the target launcher of the project. It's the recommended way to work with it. It manages the env variables of common tasks and executes only the steps that need to be run.

$ make
Available targets:

- make init       Check the dependencies and prompt to install if needed
- make clean      Clean the build artifacts

- make test            Run unit tests, locally
- make test-coverage   Generate an HTML coverage report under ./report

- make sync-tests       Scaffold or sync tree files into solidity tests
- make check-tests      Checks if solidity files are out of sync
- make markdown-tests   Generates a markdown file with the test definitions rendered as a tree

- make predeploy-testnet        Simulate a deployment to the testnet
- make predeploy-prodnet        Simulate a deployment to the production network

- make deploy-testnet        Deploy to the testnet and verify
- make deploy-prodnet        Deploy to the production network and verify

- make refund   Refund the remaining balance left on the deployment account

Run make init:

  • It ensures that Foundry is installed
  • It runs a first compilation of the project
  • It copies .env.example into .env

Next, customize the values of .env and optionally .env.test.

Understanding .env.example

The env.example file contains descriptions for all the initial settings. You don't need all of these right away but should review prior to fork tests and deployments

Deployment

Check the available make targets to simulate and deploy the smart contracts:

- make predeploy-testnet     Simulate a deployment to the defined testnet
- make predeploy-prodnet     Simulate a deployment to the defined production network
- make deploy-testnet        Deploy to the defined testnet network and verify
- make deploy-prodnet        Deploy to the production network and verify

Deployment Checklist

  • I have cloned the official repository on my computer and I have checked out the corresponding branch
  • I am using the latest official docker engine, running a Debian Linux (stable) image
    • I have run docker run --rm -it -v .:/deployment debian:bookworm-slim
    • I have run apt update && apt install -y make curl git vim neovim bc
    • I have run curl -L https://foundry.paradigm.xyz | bash
    • I have run source /root/.bashrc && foundryup
    • I have run cd /deployment
    • I have run make init
    • I have printed the contents of .env and .env.test on the screen
  • I am opening an editor on the /deployment folder, within the Docker container
  • The .env file contains the correct parameters for the deployment
    • I have created a brand new burner wallet with cast wallet new and copied the private key to DEPLOYMENT_PRIVATE_KEY within .env
    • I have reviewed the target network and RPC URL
  • All the tests run clean (make test)
  • Target test network
    • I have run a preview deployment on the testnet
      • make predeploy-testnet
    • I have deployed my contracts successfully to the target testnet
      • make deploy-testnet
    • I have tested that these contracts work successfully
  • Target production network
  • My deployment wallet is a newly created account, ready for safe production deploys.
  • My computer:
    • Is running in a safe location and using a trusted network
    • It exposes no services or ports
    • The wifi or wired network in use does not expose any ports to a WAN
  • I have previewed my deploy without any errors
    • make predeploy-prodnet
  • The deployment wallet has sufficient native token for gas
    • At least, 15% more than the estimated simulation
  • make test still run clean
  • I have run git status and it reports no local changes
  • The current local git branch (main) corresponds to its counterpart on origin
    • I confirm that the rest of members of the ceremony pulled the last commit of my branch and reported the same commit hash as my output for git log -n 1
  • I have initiated the production deployment with make deploy-prodnet

Post deployment checklist

  • The deployment process completed with no errors
  • The factory contract was deployed by the deployment address
  • All the project's smart contracts are correctly verified on the reference block explorer of the target network.
    • This also includes contracts that aren't explicitly deployed (deployed on demand)
  • The output of the latest deployment-*.log file corresponds to the console output
  • I have transferred the remaining funds of the deployment wallet to the address that originally funded it
    • make refund

Manual deployment (CLI)

The equivalent commands can also be run from the command line:

# Load the env vars
source .env
# run unit tests
forge test --no-match-path "test/fork/**/*.sol"
# Set the right RPC URL
RPC_URL="https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
# Run the deployment script

# If using Etherscan
forge script --chain "$NETWORK" script/DeployGauges.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify

# If using BlockScout
forge script --chain "$NETWORK" script/DeployGauges.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify --verifier blockscout --verifier-url "https://sepolia.explorer.mode.network/api\?"

If you get the error Failed to get EIP-1559 fees, add --legacy to the command:

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

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

forge script --chain "$NETWORK" script/DeployGauges.s.sol:Deploy --rpc-url "$RPC_URL" --verify --legacy --private-key "$DEPLOYMENT_PRIVATE_KEY" --resume

OSx protocol overview

OSx DAO's 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 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 define who can do what, and where.

A permission looks like:

  • An address who holds MY_PERMISSION_ID on a target contract where

Brand new DAO's are deployed with a ROOT_PERMISSION assigned to its creator, but the DAO will typically deployed by the DAO factory, which will install all the requested plugins and drop the ROOT permission after the set up is done.

Managing permissions is made via two functions that are called on the DAO:

function grant(address _where, address _who, bytes32 _permissionId);

function revoke(address _where, address _who, bytes32 _permissionId);

Permission Conditions

For the cases where an unrestricted permission is not derisable, a Permission Condition can be used.

Conditional permissions look like this:

  • An address who holds MY_PERMISSION_ID on a target contract where, only when the condition contract approves it

Conditional permissions are granted like this:

function grantWithCondition(
  address _where,
  address _who,
  bytes32 _permissionId,
  IPermissionCondition _condition
);

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

Testing

See the test tree file for a visual representation of the implemented tests.

Tests can be described using yaml files. They will be automatically transformed into solidity test files with bulloak.

Create a file with .t.yaml extension within the test folder and describe a hierarchy of test cases:

# MyTest.t.yaml

MyContractTest:
- given: proposal exists
  comment: Comment here
  and:
  - given: proposal is in the last stage
    and:

    - when: proposal can advance
      then:
      - it: Should return true

    - when: proposal cannot advance
      then:
      - it: Should return false

  - when: proposal is not in the last stage
    then:
    - it: should do A
      comment: This is an important remark
    - it: should do B
    - it: should do C

- when: proposal doesn't exist
  comment: Testing edge cases here
  then:
  - it: should revert

Then use make to automatically sync the described branches into solidity test files.

$ make
Available targets:
# ...
- make sync-tests       Scaffold or sync tree files into solidity tests
- make check-tests      Checks if solidity files are out of sync
- make markdown-tests   Generates a markdown file with the test definitions rendered as a tree

$ make sync-tests

The final output will look like a human readable tree:

# MyTest.tree

MyContractTest
├── Given proposal exists // Comment here
│   ├── Given proposal is in the last stage
│   │   ├── When proposal can advance
│   │   │   └── It Should return true
│   │   └── When proposal cannot advance
│   │       └── It Should return false
│   └── When proposal is not in the last stage
│       ├── It should do A // Careful here
│       ├── It should do B
│       └── It should do C
└── When proposal doesn't exist // Testing edge cases here
    └── It should revert

About

A library of OSx conditions designed to provide fine grained control on granted permissions

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published