Adopting and revoking laws
The Powers protocol uses laws as modular, role-restricted governance actions. Laws are the building blocks of the protocol's governance system, allowing for flexible and customizable governance rules.
Law System Overview
Law Structure
Each law is represented by an ActiveLaw
struct containing:
targetLaw
: The address of the law contractactive
: Boolean indicating if the law is currently active
Law Initialization Data
When adopting a law, the following data is required (LawInitData
struct):
nameDescription
: Human-readable description of the lawtargetLaw
: Address of the law contractconfig
: Additional configuration data for the lawconditions
: Governance conditions for the law
Law Management Functions
Initial Law Adoption
The initial set of laws is adopted through the constitute
function:
function constitute(LawInitData[] memory constituentLaws) external
The function:
Can only be called once by an admin
Can only be called before any other law adoption
Initializes each law in the array
Sets
_constituteExecuted
to trueEmits
LawAdopted
events for each law
Adopting Additional Laws
New laws can be adopted through the adoptLaw
function:
function adoptLaw(LawInitData memory lawInitData) public
The function:
Can only be called through the protocol itself
Verifies the target contract implements the
ILaw
interfaceIncrements the
lawCount
Initializes the law with the provided data
Emits a
LawAdopted
event
Revoking Laws
Laws can be revoked through the revokeLaw
function:
function revokeLaw(uint16 lawId) public
The function:
Can only be called through the protocol itself
Verifies the law is currently active
Sets the law's active status to false
Emits a
LawRevoked
event
Law Queries
Checking Law Status
The getActiveLaw
function returns information about a law:
function getActiveLaw(uint16 lawId) external view returns (address law, bytes32 lawHash, bool active)
Law Conditions
Laws can be queried for their conditions through the law contract:
function getConditions(address powers, uint16 lawId) public view returns (Conditions memory conditions)
Important Considerations
1. Law Adoption Restrictions
Initial laws can only be adopted once through
constitute
Only the protocol itself can adopt or revoke laws
Laws must implement the
ILaw
interfaceLaw IDs start at 1 (0 is used as a default 'false' value)
Laws cannot be modified after adoption
2. Law Implementation Requirements
Must implement the
ILaw
interfaceMust provide validation logic
Must handle state changes
Must return execution data
Must implement proper access controls
3. Common Pitfalls
Laws cannot be re-adopted after revocation
Law conditions cannot be modified after adoption
Law addresses cannot be changed
Active laws cannot be overwritten
Law IDs are sequential and cannot be reused
4. Security Considerations
Laws should be thoroughly tested before adoption
Law conditions should be carefully designed
Role restrictions should be properly implemented
State changes should be properly validated
Execution data should be properly formatted
5. Best Practices
Use clear and descriptive law names
Implement proper validation in laws
Document law conditions and requirements
Test laws thoroughly before adoption
Consider gas implications of law execution
Implement proper error handling
Use events for important state changes
Consider upgrade paths for laws
6. Gas Optimization
Law data is stored efficiently
Active status is stored as a boolean
Law addresses are stored as addresses
Law hashes are computed on-demand
Conditions are stored in the law contract
7. Law Lifecycle
Development
Implement the
ILaw
interfaceAdd validation logic
Add state management
Add execution logic
Test thoroughly
Adoption
Prepare law initialization data
Call
adoptLaw
orconstitute
Verify law is active
Test law functionality
Usage
Call law through
request
orpropose
Monitor law execution
Handle law responses
Manage law state
Revocation
Call
revokeLaw
when neededVerify law is inactive
Handle any cleanup needed
Consider replacement law
Last updated