This tutorial explains how to use the CommitteeGovernance contract, which manages specialized committees with their own voting domains in the Backr platform.
The CommitteeGovernance system allows for:
- Creation of specialized committees
- Management of committee membership
- Control of committee voting powers
- Function-level permissions for proposals
Each committee has:
- Name and description
- Voting power multiplier (in basis points)
- Active status
- Member list
- Allowed functions list
DEFAULT_ADMIN_ROLE
: Overall contract administrationCOMMITTEE_ADMIN_ROLE
: Committee management permissions
function createCommittee(
"Technical Review", // name
"Reviews technical implementations", // description
500 // votingPowerMultiplier (5x)
)
Important Notes:
- Only addresses with
COMMITTEE_ADMIN_ROLE
can create committees - Voting power multiplier is in basis points (100 = 1x, 1000 = 10x)
- Maximum multiplier is 10000 (100x)
Adding members:
// Add a member to committee ID 0
committeeGovernance.addMember(0, memberAddress);
Removing members:
// Remove a member from committee ID 0
committeeGovernance.removeMember(0, memberAddress);
Requirements:
- Only
COMMITTEE_ADMIN_ROLE
can add/remove members - Committee must exist
- Cannot add existing members
- Cannot remove non-members
Allow functions for committee proposals:
// Allow a function for committee ID 0
bytes4 functionSelector = bytes4(keccak256("functionName(paramTypes)"));
committeeGovernance.allowFunction(0, functionSelector);
// Check if an address is a committee member
bool isMember = committeeGovernance.isMember(
0, // committeeId
memberAddress // address to check
);
// Get member's voting power multiplier
uint256 multiplier = committeeGovernance.getVotingPowerMultiplier(
0, // committeeId
memberAddress // member address
);
// Check if a function can be proposed by a committee
bool isAllowed = committeeGovernance.isFunctionAllowed(
0, // committeeId
bytes4(keccak256("functionName(paramTypes)")) // functionSelector
);
The contract emits several important events:
-
CommitteeCreated(uint256 committeeId, string name)
- Triggered when a new committee is created
- Includes committee ID and name
-
MemberAdded(uint256 committeeId, address member)
- Triggered when a member is added to a committee
- Includes committee ID and member address
-
MemberRemoved(uint256 committeeId, address member)
- Triggered when a member is removed from a committee
- Includes committee ID and member address
-
FunctionAllowed(uint256 committeeId, bytes4 functionSelector)
- Triggered when a function is allowed for a committee
- Includes committee ID and function selector
-
Committee Creation
- Use descriptive names and clear descriptions
- Set appropriate voting power multipliers
- Document committee purposes and responsibilities
-
Member Management
- Regularly review committee membership
- Maintain appropriate committee sizes
- Document member selection criteria
-
Function Permissions
- Carefully review functions before allowing
- Document allowed functions for each committee
- Regularly audit function permissions
-
Voting Power
- Set multipliers based on committee importance
- Consider impact on overall governance
- Document multiplier rationale
Here's a complete example of setting up and managing a committee:
// 1. Create a technical committee
committeeGovernance.createCommittee(
"Technical Committee",
"Reviews and approves technical implementations",
500 // 5x voting power
);
// 2. Add committee members
address[] memory technicalExperts = [
address(0x123...),
address(0x456...),
address(0x789...)
];
for (uint i = 0; i < technicalExperts.length; i++) {
committeeGovernance.addMember(0, technicalExperts[i]);
}
// 3. Allow specific functions
bytes4[] memory allowedFunctions = [
bytes4(keccak256("upgradeContract(address)")),
bytes4(keccak256("setTechnicalParameters(uint256)"))
];
for (uint i = 0; i < allowedFunctions.length; i++) {
committeeGovernance.allowFunction(0, allowedFunctions[i]);
}
// 4. Verify setup
bool isMember = committeeGovernance.isMember(0, technicalExperts[0]);
uint256 multiplier = committeeGovernance.getVotingPowerMultiplier(0, technicalExperts[0]);
bool canPropose = committeeGovernance.isFunctionAllowed(0, allowedFunctions[0]);
-
Role Management
- Carefully manage admin role assignments
- Regularly audit role holders
- Use multi-sig for admin actions
-
Voting Power
- Consider impact of multipliers on governance
- Monitor for potential voting power concentration
- Regular review of multiplier settings
-
Function Permissions
- Audit allowed functions regularly
- Consider function dependencies
- Document permission changes
-
Committee Structure
- Maintain appropriate committee sizes
- Regular review of committee effectiveness
- Document committee changes
The CommitteeGovernance contract works in conjunction with the main Governance contract:
- Committee members get voting power multipliers for their domain
- Proposals for allowed functions can be made by committee members
- Committee structure provides specialized governance domains
Remember to:
- Coordinate committee actions with main governance
- Consider overall governance impact
- Document committee-governance interactions