Lucene search

K
code423n4Code4renaCODE423N4:2023-08-LIVEPEER-FINDINGS-ISSUES-162
HistorySep 06, 2023 - 12:00 a.m.

using increaseTotalStakeUncheckpointed() instead of increaseTotalStake() can lead to inconsistent transcoder state

2023-09-0600:00:00
Code4rena
github.com
4
vulnerability
stake increase
transcoder state
governance
mitigation

Lines of code
<https://github.com/code-423n4/2023-08-livepeer/blob/a3d801fa4690119b6f96aeb5508e58d752bda5bc/contracts/bonding/BondingManager.sol#L1459&gt;

Vulnerability details

Impact

This allows a transcoder to increase their voting power without actually increasing their stake.

Proof of Concept

The relevant code that uses increaseTotalStakeUncheckpointed() and skips transcoder state checkpointing is in the updateTranscoderWithRewards() function: <https://github.com/code-423n4/2023-08-livepeer/blob/a3d801fa4690119b6f96aeb5508e58d752bda5bc/contracts/bonding/BondingManager.sol#L1488&gt;

Using increaseTotalStakeUncheckpointed() instead of increaseTotalStake() can lead to inconsistent transcoder state.
The key difference is that increaseTotalStake() has an autoCheckpoint modifier which calls _checkpointBondingState(), while increaseTotalStakeUncheckpointed() does not.
_checkpointBondingState() updates the historical record of the transcoderโ€™s stake and reward state via the BondingVotes contract. This historical record is used for calculating voting power in the governance system.
By skipping the checkpoint, increaseTotalStakeUncheckpointed() causes the transcoderโ€™s voting power to become inconsistent with its actual stake.
For example:

  1. Transcoder A has 100 LPT bonded, last reward round 10
  2. Call increaseTotalStakeUncheckpointed(A, 50 LPT)
  3. A now has 150 LPT bonded, but BondingVotes still records A as having 100 LPT at round 10
  4. Aโ€™s voting power will be calculated incorrectly based on the outdated BondingVotes records

Tools Used

Manual

Recommended Mitigation Steps

increaseTotalStakeUncheckpointed() should only be used in cases where the caller guarantees it will checkpoint the state later, like in processRebond(). For general stake increases, increaseTotalStake() should be used.

Assessed type

Other


The text was updated successfully, but these errors were encountered:

All reactions