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
Section titled “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:
- 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. - Run checks: Before any action is executed,
Powers.solchecks the relevant Mandate conditions to validate the request. This ensures that all governance actions adhere to the rules defined by the organisation’s mandates. - 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. It prefers to save as much data as possible on-chain to reduce reliance on off-chain indexing.
- Enforce Outcomes: After a
Mandate.solcontract has validated an action and returned the execution data,Powers.solis 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
Section titled “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
Section titled “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
Section titled “Role Management”The process of managing roles involves a few key functions.
Assigning a Role
Section titled “Assigning a Role”An admin uses assignRole() to grant a specific role to a user’s account.
Revoking a Role
Section titled “Revoking a Role”An admin uses revokeRole() to remove a role from a user’s account.
Labelling a Role
Section titled “Labelling a Role”To make roles easier to identify, an admin can use labelRole() to give it a human-readable name.
Blacklisting an Address
Section titled “Blacklisting an Address”An admin uses blacklistAddress() to prevent an account from interacting with the protocol.
Mandates: Adopting and Revoking
Section titled “Mandates: Adopting and Revoking”Mandates are modular, role-restricted governance actions and the building blocks of the protocol’s governance system.
Mandate Management
Section titled “Mandate Management”Managing the lifecycle of mandates is a core administrative task.
Initial Constitution
Section titled “Initial Constitution”The organisation is born when an admin calls constitute() with the initial set of mandates (an array of MandateInitData). This can only be done once. The constitution phase is then closed using closeConstitute().
Adopting New Mandates
Section titled “Adopting New Mandates”As the organisation evolves, new mandates can be added by an admin using adoptMandate().
Revoking Existing Mandates
Section titled “Revoking Existing Mandates”If a mandate becomes obsolete, an admin can remove it using revokeMandate().
Actions: Proposing, Voting, and Executing
Section titled “Actions: Proposing, Voting, and Executing”Proposing and Voting
Section titled “Proposing and Voting”Proposals are used when an action requires community consensus.
Creating a Proposal
Section titled “Creating a Proposal”A user calls propose() with the mandate details and a metadata URI description.
Voting Period
Section titled “Voting Period”The proposal enters a voting period defined by the mandate.
Casting Votes
Section titled “Casting Votes”Eligible voters use castVote() or castVoteWithReason().
Resolution
Section titled “Resolution”The proposal can be Succeeded, Defeated, or Cancelled.
Executing Actions
Section titled “Executing Actions”The execution flow involves a request and callback logic between Powers.sol and the Mandate contracts.
Request Action
Section titled “Request Action”A user initiates an action by calling request() in Powers.sol with the mandate details and a metadata URI description.
Mandate Validation
Section titled “Mandate Validation”Powers.sol calls executeMandate() on the target mandate contract, which validates the request and prepares the execution data.
Fulfill Action
Section titled “Fulfill Action”The mandate calls back to Powers.sol’s fulfill() function, which executes the transaction and marks the action as complete.
Technical Specifications
Section titled “Technical Specifications”Source
Section titled “Source”See the github repo here.
Key Differences from OpenZeppelin’s Governor.sol:
Section titled “Key Differences from OpenZeppelin’s Governor.sol:”- DAO actions must be encoded in role-restricted external contracts (mandates) following the
IMandateinterface. - Proposing, voting, cancelling and executing actions are role-restricted along the target mandate.
- All DAO actions must run through the governance flow provided by
Powers.sol. - Uses a non-weighted voting mechanism: one account has one vote. Accounts vote with their roles, not with their tokens.
- Core protocol is intentionally minimalistic - complexity (multi-chain, oracles, timelocks, etc.) must be integrated through mandates.
State Variables
Section titled “State Variables”_actions:mapping(uint256 actionId => Action)mandates:mapping(uint16 mandateId => AdoptedMandate)roles:mapping(uint256 roleId => Role)_blacklist:mapping(address account => bool blacklisted)
Functions
Section titled “Functions”- Governance:
request,fulfill,propose,cancel,castVote,castVoteWithReason - Admin:
constitute,closeConstitute,adoptMandate,revokeMandate,assignRole,revokeRole,labelRole,blacklistAddress,setUri,setTreasury
Structs
Section titled “Structs”Action: Tracks a proposal’s state, voting information, and execution data.AdoptedMandate: Tracks an active mandate’s address, status, and conditions.Role: Tracks role assignments and membership.Conditions: Defines the governance parameters for a mandate (quorum, voting period, etc.).MandateInitData: Used for initializing mandates during constitution or adoption.
Events
Section titled “Events”- Governance:
ActionRequested,ProposedActionCreated,ProposedActionCancelled,VoteCast - Admin:
RoleSet,RoleLabel,MandateAdopted,MandateRevoked,BlacklistSet,Powers__Initialized