openlawteam / tribute-contracts

A new modular DAO framework, inspired by the Moloch smart contracts
https://tributedao.com
MIT License
295 stars 109 forks source link
daos modular smart-contracts
Tribute DAO Framework Logo

Tribute DAO Framework

A modular, low cost and extensible set of contracts to build your DAO on Ethereum


Tests Slither Coverage Slither Discord Twitter

TributeLabs.xyz »

DocsDemo

Contents

Overview

TributeDAO is a new modular, low cost DAO framework. The framework aims to improve DAOs by fixing the:

The TributeDAO framework aims to address these issues, as part of our quest to make DAOs the dominant form of organization. As the growing number of participants in DAOs know, there is no “one size fits all” for managing any organization. DAOs need low cost and easy to develop components that can be assembled like lego blocks to fit the needs of the organization and its membership.

Proposed Evolution of MolochDAO Framework

The TributeDAO framework is our team's tribute to the MolochDAO ecosystem. As many know, MolochDAO brought new life to DAOs. Through an elegant smart contract design, this smart contract framework brought DAOs back to life, helping us push beyond the fiery depths of “The DAO.”

Last year, we worked to evolve the initial MolochDAO smart contracts by assisting with the creation of Moloch v2, which enabled multiple token support, “guildkicks” to remove unwanted members, and “loot” to issue non-voting shares still entitled to financial distributions. These upgraded contracts were built with “venture” and similar investment transactions in mind, allowing for more effective swaps and control over tokenized assets and membership.

The TributeDAO framework hopes to provide teams looking to deploy DAOs with several enhancements and improvements, including:

Inspired by the hexagonal architecture design pattern we believe that we can have additional layers of security, and break the main contract into smaller contracts. With that, we create loosely coupled modules/contracts, easier to audit, and can be easily connected to the DAO.

Tribute DAO Architecture

laoland_hexagon_architecture

The main design goal is to limit access to the smart contracts according at layer boundaries. The External World (i.e. RPC clients) can access the core contracts only via Adapters, never directly. Every adapter contains all the necessary logic and data to update/change the state of the DAO in the DAORegistry Contract. The Core Contract tracks all the state changes of the DAO, and an Adapter tracks only the state changes in its own context. Extensions enhance the DAO capabilities and simplify the Core Contract code. The information always flows from the External World to the Core Contracts, never the other way around. If a Core Contract needs external info, it must be provided by an Adapter and/or an Extension instead of calling External World directly.

There are five main components in the Tribute architecture outlined further below.

Core Contracts

The core contracts serve as the spine for the Tribute DAO framework and act as a DAO registry, creating a digital version of "division of corporations." These contracts compose the DAO itself, and make it cheaper and easier to deploy a DAO. These contracts directly change the DAO state without the need of going through an adapter or extension (described further below). A core contract never pulls information directly from the external world. For that we use Adapters and Extensions, and the natural information flow is always from the external world to the core contracts.

There are three core contracts as part of the Tribute DAO framework, including a:

Adapters and Extensions

Once a DAO is created using the above core contracts, they can be extended and modified with adapters and extensions. Adapters and extensions make it easy to assemble a DAO like lego blocks, by adding to a DAO narrowly-defined, tested, and extensible smart contracts created for specific purposes. Adapters and extensions make DAOs more modular, upgradeable, and also enable us to work together to build robust DAO tooling. They can be added to a TributeDAO via a DAO vote.

Adapters

There are currently 12 adapters implemented in the Tribute DAO framework and these adapters make the Tribute DAO framework feature compatible with Moloch v2:

The range of potential adapters will expand over time and likely will include:

Creating an adapter is straight forward and should save developers engineering time. Each adapter needs to be configured with the Access Flags in order to access the Core Contracts, and/or Extensions. Otherwise the Adapter will not able to pull/push information to/from the DAO.

Please note:

Extensions

Extensions are conceived to isolate the complexity of state changes from the DAORegistry contract, and to simplify the core logic. Essentially an Extension is similar to an Adapter, but the main difference is that it is used by several adapters and by the DAORegistry - which end up enhancing the DAO capabilities and the state management without cluttering the DAO core contract.

Access Control Layer

The Access Control Layer (ACL) is implemented using Access Flags to indicate which permissions an adapter must have in order to access and modify the DAO state. The are 3 main categories of Access Flags:

The Access Flags of each adapter must be provided to the DAOFactory when the daoFactory.addAdapters function is called passing the new adapters. These flags will grant the access to the DAORegistry contract, and the same process must be done to grant the access of each Adapter to each Extension (function daoFactory.configureExtension).

The Access Flags are defined in the DAORegistry using the modifier hasAccess. For example, a function with the modifier hasAccess(this, AclFlag.REPLACE_ADAPTER) means the adapter calling this function needs to have the Access Flag REPLACE_ADAPTER enabled, otherwise the call will revert. In order to create an Adapter with the proper Access Flags one needs to first map out all the functions that the Adapter will be calling in the DAORegistry and Extensions, and provide these Access Flags using the DAO Factory as described above.

You can find more information about the purpose of each access flag at DAO Registry - Access Flags.

Quickstart

Install all dependencies

npm ci

Creating a .env file at the root

cp .sample.env .env

Compile contracts

npm run compile

Deploy contracts

Deploy contracts to networks such as sepolia, harmonytest, polygontest, ganache, mainnet, harmony, polygon or avalanche.

npm run deploy sepolia

For more information about the deployment, see the in logs logs/contracts

Verify contracts

npm run verify sepolia

OR

npm run verify mainnet

DApp setup

In the same .env file created under the tribute-contracts folder, set the following environment variables:

######################## Tribute UI env vars ########################

# Configure the UI to use the Sepolia network for local development
REACT_APP_DEFAULT_CHAIN_NAME_LOCAL=SEPOLIA

# It can be the same value you used for the Tribute DAO deployment.
REACT_APP_INFURA_PROJECT_ID_DEV=YOUR_INFURA_API_KEY

# The address of the Multicall smart contract deployed to the Sepolia network.
# Copy that from the tribute-contracts/build/contracts-sepolia-YYYY-MM-DD-HH:mm:ss.json
REACT_APP_MULTICALL_CONTRACT_ADDRESS=0x...

# The address of the DaoRegistry smart contract deployed to the Sepolia network.
# Copy that from the tribute-contracts/build/contracts-sepolia-YYYY-MM-DD-HH:mm:ss.json
REACT_APP_DAO_REGISTRY_CONTRACT_ADDRESS=0x...

# Enable Sepolia network for Tribute UI
REACT_APP_ENVIRONMENT=development

Make sure you have set the correct addresses for REACT_APP_MULTICALL_CONTRACT_ADDRESS & REACT_APP_DAO_REGISTRY_CONTRACT_ADDRESS.

DAO Launch

npm run docker

Linter

List the problems found in project files

npm run lint

Fix the lint issues

npm run lint:fix

Slither

npm run slither

Tests

npm run compile && npm test

Environment variables

Contracts:

Snapshot-hub:

Tribute-UI:

Release

  1. Checkout master and pull the latest
  2. Locally run npm run release
  3. Choose a new semver version number
  4. In the background the following will happen:
    1. the package.json version will be bumped
    2. a new Git tag is created
    3. package version bump and tag pushed to master
    4. GitHub Release page will open, set the release name, edit the changelog if needed, and publish
    5. publish.yaml will execute (due to the new release tag) to publish the new package version to the NPM registry.
  5. Done!

Contribute

Tribute exists thanks to its contributors. There are many ways you can participate and help build high quality software. Check out the contribution guide!

Community

Join us on Discord.

Thank You

THANK YOU to all coders, designers, auditors, and any individual who have contributed with ideas, resources, and energy to this and previous versions of this project. Thank you all.

License

Tribute is released under the MIT License.