Platform: Code4rena
Start Date: 31/08/2023
Pot Size: $55,000 USDC
Total HM: 5
Participants: 30
Period: 6 days
Judge: hickuphh3
Total Solo HM: 2
Id: 282
League: ETH
Rank: 14/30
Findings: 1
Award: $562.13
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: catellatech
Also found by: 0x3b, ADM, Banditx0x, JayShreeRAM, Krace, Sathish9098
The Livepeer onchain treasury update introduces a governance mechanism for managing funds and executing proposals within the Livepeer protocol. This mechanism utilizes several new contracts and updates existing ones to facilitate on-chain governance. Below, I reviewed the key components, terms, parameters, and contracts involved in this onchain update.
1 . Delegator Override
One of the unique patterns in this governance system is the ability for delegators to override their transcoder's votes. This means that even if a delegator has delegated their tokens to a transcoder, they can cast their own vote on a proposal, potentially differing from their transcoder's vote. This allows for more fine-grained control over voting preferences.
2 . Customized Vote Counting
The LivepeerGovernor contract includes a custom implementation for vote counting, known as GovernorCountingOverridable. This custom module enables the counting of votes where both transcoders and delegators can participate, and it considers delegator overrides. This differs from typical on-chain governance systems that may not allow delegators to vote separately from their transcoders.
3 . ERC-5805 Compliance
The governance system implements aspects of the ERC-5805 standard to handle voting power and delegation. While ERC-5805 is not widely adopted, it offers a unique approach to on-chain governance and delegation that differs from more common governance standards.
OpenZeppelin Governance Primitives
The governance system leverages the Governance primitives provided by OpenZeppelin, which includes modules for proposal creation, voting, and execution. This is a common pattern in many on-chain governance systems to ensure security and modularity.
Quorum and Proposal Thresholds
The system implements common patterns such as quorum requirements and proposal thresholds. Quorum ensures a minimum level of participation in voting, while the proposal threshold sets the minimum amount of voting power required to create a proposal. These patterns help maintain the integrity of the governance process.
Timelock for Proposal Execution
The use of a timelock mechanism, inherited from TimelockControllerUpgradeable, is a common pattern in governance systems. It enforces a delay between proposal approval and execution, providing a safety net for the community to react if necessary.
Checkpointing
The system uses checkpointing to record and track the state of various parameters, including bonding state and total active stake. Checkpointing is a common pattern to ensure that the historical state can be referenced accurately for voting and tallying.
Decentralized Governance
The governance system follows the pattern of decentralized governance, where decisions are made collectively by token holders. This is a fundamental pattern in on-chain governance systems.
1 . Checkpointing Total Active Stake
To checkpoint the total active stake of every round, the ROUNDS_MANAGER.initializeRound() can be used to indirectly checkpoint the total active stake for the protocol on that round.
After setCurrentRoundTotalActiveStake is called in round r, the expectation is that:
1 . BondingVotes.totalSupply() returns exactly BONDING_MANAGER.currentRoundTotalActiveStake() during the same round. 2 . BondingVotes.getPastTotalSupply(r) will immutably return the same value above in the future.
2 . Checkpointing Bonding State
The main changes to BondingManager were internal, to make sure we checkpoint all the bonding state every time any change is made to an account state.
The optimal gas implementation of this would also make sure the BondingManager never checkpoints the same address multiple times on a single function call.
In practical terms, it can be defined that after any write function called on the BONDING_MANAGER (including the checkpointBondingState below), the checkpointed state of all involved accounts should follow that mutation consistently.
3 . Interface additions
contract BondingManager { function checkpointBondingState(address _account) external; }
The BondingVotes contract is a key component of the Livepeer protocol, designed to manage and track voting power within the system. It leverages checkpointing mechanisms to capture and record the state of various stakeholders, including delegators and transcoders, in the Livepeer network. This report will provide an in-depth analysis of the contract's functions, their purposes, and their expected behaviors.
1 . Checkpointing State - 1.1 checkpointBondingState
- 1.2 checkpointTotalActiveStake
2. State Lookup The BondingVotes contract provides functions for looking up the checkpointed state to ensure consistency and integrity of data.
- 2.1 getTotalActiveStakeAt
This function returns the total active stake at the start of a specified round. It considers various scenarios, including the absence of checkpoints, existence of checkpoints, and checkpoint values before and after the searched round.
- 2.2 hasCheckpoint
This utility function checks whether a specific account has any checkpoints already registered, helping initialize account checkpoints when necessary.
- 2.3 getBondingStateAt
This function retrieves the active stake and delegate of an account in a specified round, calculated using the checkpoint with the highest startRound lower or equal to the specified round. It behaves differently for transcoders and delegators, ensuring accurate data retrieval.
3. ERC-20 Metadata
The BondingVotes contract implements optional ERC-20 metadata methods to improve interoperability with existing tools. These methods return specific metadata about the token.
name: Returns "Livepeer Voting Power." symbol: Returns "vLPT." decimals: Returns 18.
4 . ERC-5805
The BondingVotes contract partially implements ERC-5805, which specifies how to express voting power with checkpointing and delegation mechanisms. The contract adheres to the following ERC-5805 functions:
5. Caveats
The BondingVotes contract has some known divergences from ERC-5805 and IERC5805Upgradeable expectations:
This is an important component of a governance system that complements the BondingCheckpointsVotes module by providing vote counting logic. It is designed to be as similar as possible to the off-chain indexer logic described in LIP-16, providing a robust and flexible voting mechanism for decentralized decision-making within a blockchain ecosystem.
Key Components and Functions:
1 . IVotes Interface This interface defines the methods for interacting with the voting system. It includes functions for retrieving voting-related information such as name, symbol, decimals, total supply, and delegated voting power at a specific timepoint.
2 . GovernorCountingOverridable Contract This abstract contract extends the GovernorUpgradeable contract and implements the vote counting logic. It introduces several key functions and properties:
_GovernorCountingOverridable_init(_quota): This internal function initializes the module with a provided quota, which is expressed in 6-digit decimal precision compatible with the protocol's MathUtils. The quota is crucial for calculating whether a vote succeeds or not.
quota(): This public view function returns the configured quota value for calculating the success of a vote. The quota is set during the initialization of the Governor and is not updatable without a future upgrade.
COUNTING_MODE(): This function returns a string representing the counting mode, which is "support=bravo&quorum=for,abstain,against" in this case.
hasVoted(_proposalId, _account): This function checks whether a specific account has already cast a vote on a particular proposal. It indicates whether _countVote has been called for the same account and proposal.
proposalVotes(_proposalId): This function returns the sum of votes made for, against, and abstain for a given proposal. It collects voting data from _countVote for each vote type.
_quorumReached(_proposalId): This internal view function determines whether the sum of votes (for, against, and abstain) meets the minimum defined threshold (quorum). It retrieves the quorum from the GovernorUpgradeable contract's quorum() virtual function and considers all vote types for quorum calculation.
_voteSucceeded(_proposalId): This internal view function determines whether a proposal has been approved based on the voting outcome. It calculates the quota percentage from the configured quota variable and considers only the "For" and "Against" votes.
_countVote(...): This internal virtual function implements the logic for counting votes when a vote is cast on a proposal. It considers different scenarios, including when a transcoder votes first, when delegators vote first, when delegators vote after their transcoder, and when a transcoder votes after their delegators.
The votes() function, which returns an instance of the IVotes interface, needs to be implemented by a concrete LivepeerGovernor contract, providing the contract to use for voting power.
The primary purpose of the Treasury Timelock Controller is to act as an essential component of the governance mechanism for the Livepeer protocol. It serves as an interface to interact with the TimelockControllerUpgradeable contract, allowing the system to enforce time delays for certain administrative actions, ensuring a level of security and oversight.
Treasury roles and their responsibilities as configured in production deployments:
1 . TIMELOCK_ADMIN_ROLE
2 . PROPOSER_ROLE
3 . EXECUTOR_ROLE
4 . CANCELLER_ROLE
The LivepeerGovernor contract is a complex smart contract that brings together various elements to facilitate on-chain governance. It inherits functionality and features from several other contracts, both non-functional and functional:
1 . Non-functional Inheritance
ManagerProxyTarget: This contract supports contract upgradability, allowing for future upgrades consistent with the rest of the protocol contracts. Initializable (OpenZeppelin): Provides abstractions for initializing proxied contracts.
2 . Functional Inheritance
1. Modularity and Code Separation
The codebase is well-structured and modular, with distinct contracts handling various governance functions. Each contract has a specific purpose and encapsulates related functionality.
2. Inheritance and Reusability:
The codebase effectively utilizes inheritance to reuse functionality from OpenZeppelin contracts, known for their security and reliability.
3. Documentation and Comments
Detailed documentation is provided, explaining the purpose and functionality of each contract, parameter, and function. Comments within the code clarify complex logic and the reasoning behind certain decisions.
4. Initialization and Upgradability
Initialization is handled well using the Initializable contract from OpenZeppelin. The contract LivepeerGovernor incorporates the ManagerProxyTarget for upgradability, ensuring future updates can be made without disrupting the existing system.
5. Parameterization and Configurability
The codebase allows parameterization of key variables such as voting delay, voting period, threshold, and quorum. These parameters can be updated through governance actions, providing flexibility for adjustments in the future.
6. Security
The codebase relies on trusted OpenZeppelin contracts for core governance functionality, which have undergone extensive security audits. Proper access control mechanisms are in place to restrict actions to authorized roles.
7. Error Handling
Error handling is implemented to revert transactions when unauthorized actions are attempted. Errors are handled gracefully with informative error messages.
8. Consistency and Standards
The codebase adheres to established standards such as ERC-5805 for voting power and ERC-20 for token metadata. Naming conventions and function signatures follow common Ethereum development practices.
9. Testing and Deployment
Thorough testing should be conducted to ensure the correctness and security of the contracts before deployment in a live environment.
10. Governance Processes
11. Caveats and Considerations
12. Community Involvement
LivepeerOnchain Treasury appears to be well-structured, there are several centralization risks that should be considered:
1 . Token Distribution
2 . Delegate Voting Power
3 . Minimum Quorum
4 . Proposal Threshold
5 . Governor Timelock
6 . Quota and Quorum Changes
7 . Checkpointing and Governance Power
8 . Lack of Voting Participation
9 . Single Implementation
10 . Governance Proposals
After conducting an audit of the Livepeer Onchain Treasury Update, I have gained valuable insights into the intricacies of this on-chain governance system and its associated smart contracts. Here's what I've learned from this audit:
Governance Contracts The Livepeer Onchain Treasury Update introduces several key contracts that form the foundation of the governance system. These contracts include BondingVotes, Treasury, and LivepeerGovernor. Each contract serves a specific role in the governance process, from managing voting power to executing proposals.
Checkpointing State The audit revealed that the BondingManager contract has undergone significant changes to implement checkpointing of total active stake and bonding state. This checkpointing process ensures that historical data is accurately recorded and maintained for voting power calculations.
Parameters and Definitions The audit provided a thorough breakdown of the parameters and definitions used within the governance system. It clarified terms such as active stake, quorum, voting delay, and proposal threshold, giving a clear understanding of how these parameters impact the decision-making process.
ERC-20 Metadata and ERC-5805 I learned that the governance contracts implement optional ERC-20 metadata methods to enhance interoperability with existing tools. Additionally, the implementation follows certain aspects of the ERC-5805 standard to express voting power, although there are acknowledged deviations from the standard.
Governor Counting and Overrides One notable aspect of the audit is the custom implementation of the GovernorCountingOverridable contract, which allows delegators to override their transcoder's votes. This customization demonstrates flexibility in the governance design to accommodate various voting scenarios.
Roles and Permissions The audit highlighted the importance of roles and permissions within the governance system. Roles are assigned to specific contracts, such as the TimelockController, to control access and actions related to governance proposals.
Initialization The LivepeerGovernor contract includes an initialization function with various initial parameters. This step is crucial for setting up the governance system with appropriate configurations.
Caveats The audit report acknowledges certain deviations from ERC-5805 and IERC5805Upgradeable standards and provides explanations for these variations. These deviations are important to consider when assessing the compliance of the governance system.
The architecture proposed for this update appears to be well-thought-out and aligned with established governance best practices. The use of OpenZeppelin's Governance primitives and the clear definitions and explanations of various components, terms, and parameters contribute to the solidity of the proposal.
The architecture is built on solid foundations, with contracts like BondingVotes and LivepeerGovernor extending from established OpenZeppelin contracts, ensuring reliability and security. The implementation of checkpointing for bonding state and active stake adds robustness to the system, especially when dealing with on-chain governance.
However, there are a few caveats and considerations to note:
The ERC-5805 and IERC5805Upgradeable should be carefully reviewed to ensure they do not introduce unexpected complexities or vulnerabilities.
The implementation of the timelock with an initial value of zero may raise questions about the potential need for an enforced delay in the future. It's important to assess whether this design choice aligns with the overall governance strategy.
It might be beneficial to include additional details on the rationale behind certain choices, especially when deviating from standard practices. This can help reviewers better understand the decision-making process.
I recommend a thorough review of the mentioned deviations from standards to ensure they do not introduce unexpected risks.
The Livepeer Onchain Treasury Upgrade exhibits a well-structured architecture, sound codebase quality, and mechanisms that align with governance principles. While no critical issues were identified in this advanced analysis, it is essential to conduct a comprehensive code review, monitor governance participation, and implement robust testing and monitoring procedures to ensure the security and effectiveness of the upgrade.
The audit provides recommendations for further improvements and risk mitigation measures. The Livepeer community should consider these recommendations while proceeding with the upgrade to enhance the governance and treasury management within the Livepeer ecosystem.
12 Hours
12 hours
#0 - c4-judge
2023-09-21T15:12:48Z
HickupHH3 marked the issue as grade-a