Skip to content

The Powers Protocol

Powers is a role-restricted governance protocol that provides a modular, flexible, decentralized, and efficient governance engine for DAOs. It is designed to be used in combination with implementations of Mandate.sol contracts.

The Role of Powers.sol

Powers.sol is the central engine of the protocol, acting as the unopinionated core of any organisation's governance structure. It is intentionally minimalistic and does not contain any specific governance logic itself. Instead, its primary responsibilities are to:

  1. Serve as the Governance Hub: All governance actions, from proposing a vote to executing a transaction, are initiated through Powers.sol. It provides a single, secure entry point for all interactions.
  2. Run checks: Before any action is executed, Powers.sol checks the relevant Mandate conditions to validate the request. This ensures that all governance actions adhere to the rules defined by the organisation's mandates.
  3. Manage State: It is the authoritative source for the organisation's state, including which mandates are active, which accounts hold which roles, and the status of all ongoing proposals and actions.
  4. Enforce Outcomes: After a Mandate.sol contract has validated an action and returned the execution data, Powers.sol is responsible for reliably executing the final transaction and updating the state accordingly.

In essence, Powers.sol acts as the immutable foundation of the organisation, providing the core mechanics for state management and execution, while the modular Mandate.sol contracts provide the flexible, adaptable governance logic. This separation makes the system both secure and highly extensible.

Roles: Assigning, Revoking and Labelling

The Powers protocol implements a role-based access control system that is fundamental to its governance mechanism.

Built-in Roles

  • ADMIN_ROLE (0): The highest privilege role, assigned to the contract deployer.
  • PUBLIC_ROLE (type(uint256).max): A special role that everyone has by default.

Role Management

The process of managing roles involves a few key functions.

Assigning a Role

An admin uses assignRole() to grant a specific role to a user's account.

Revoking a Role

An admin uses revokeRole() to remove a role from a user's account.

Labelling a Role

To make roles easier to identify, an admin can use labelRole() to give it a human-readable name.

Mandates: Adopting and Revoking

Mandates are modular, role-restricted governance actions and the building blocks of the protocol's governance system.

Mandate Management

Managing the lifecycle of mandates is a core administrative task.

Initial Constitution

The organisation is born when an admin calls constitute() with the initial set of mandates. This can only be done once.

Adopting New Mandates

As the organisation evolves, new mandates can be added by an admin using adoptMandate().

Revoking Existing Mandates

If a mandate becomes obsolete, an admin can remove it using revokeMandate().

Actions: Proposing, Voting, and Executing

Proposing and Voting

Proposals are used when an action requires community consensus.

Creating a Proposal

A user calls propose() with the mandate details.

Voting Period

The proposal enters a voting period defined by the mandate.

Casting Votes

Eligible voters use castVote() or castVoteWithReason().

Resolution

The proposal can be Succeeded, Defeated, or Cancelled.

Executing Actions

The execution flow involves a request and callback logic between Powers.sol and the Mandate contracts.

Request Action

A user initiates an action by calling request() in Powers.sol.

Mandate Validation

Powers.sol calls executeMandate() on the target mandate contract, which validates the request and prepares the execution data.

Fulfill Action

The mandate calls back to Powers.sol's fulfill() function, which executes the transaction and marks the action as complete.

Technical Specifications

Source

See the github repo here.

Key Differences from OpenZeppelin's Governor.sol:

  1. DAO actions must be encoded in role-restricted external contracts (mandates) following the IMandate interface.
  2. Proposing, voting, cancelling and executing actions are role-restricted along the target mandate.
  3. All DAO actions must run through the governance flow provided by Powers.sol.
  4. Uses a non-weighted voting mechanism: one account has one vote.
  5. Core protocol is intentionally minimalistic - complexity must be integrated through mandates.

State Variables

  • _actions: mapping(uint256 actionId => Action)
  • _mandates: mapping(uint16 mandateId => AdoptedMandate)
  • _roles: mapping(uint256 roleId => Role)
  • _deposits: mapping(address account => Deposit[])

Functions

  • Governance: request, fulfill, propose, cancel, castVote, castVoteWithReason
  • Admin: constitute, adoptMandate, revokeMandate, assignRole, revokeRole, labelRole

Structs

  • Action: Tracks a proposal's state and voting information.
  • AdoptedMandate: Tracks an active mandate's address and status.
  • Role: Tracks role assignments and membership.
  • Deposit: Tracks a deposit's amount and block number.

Events

  • Governance: ActionRequested, ActionExecuted, ProposedActionCreated, ProposedActionCancelled, VoteCast
  • Admin: RoleSet, RoleLabel, MandateAdopted, MandateRevoked