DeFiLayer 1Layer 2
14,723 OP
View results
Submission Details
Severity: medium
Invalid

Possible Incorrect Unlocked Shares Calculation When Number of Periods Is Capped

Summary

The issue occurs when the number of periods is capped by max_v2_duration in _obtain_price_params, but _unlocked_shares still calculates unlocked shares based on the full time difference (ts - last_profit_update). This discrepancy leads to an overestimation of unlocked shares, causing an incorrect total supply calculation and distorting the reported price.

Vulnerability Details

The function _obtain_price_params caps the number of periods at max_v2``duration, but unlockedshares does not account for this cap when calculating unlocked shares. This can leads to an overestimation of unlocked shares, reducing the total supply incorrectly and inflating the calculated price when the tsis really away from the adjusted last_profit_updatewhen obtaining prices.

def _obtain_price_params(parameters_ts: uint256) -> PriceParams:
params: PriceParams = self.price_params
period: uint256 = self.profit_max_unlock_time
if params.last_profit_update + period >= parameters_ts:
return params
number_of_periods: uint256 = min(
(parameters_ts - params.last_profit_update) // period,
self.max_v2_duration, //@audit Capped by max_v2_duration
)
params.total_idle += (
params.balance_of_self * (params.total_idle + params.total_debt) // params.total_supply
) * number_of_periods
params.last_profit_update += number_of_periods * period //@audit Updated with capped period
return params
def _unlocked_shares(
full_profit_unlock_date: uint256,
profit_unlocking_rate: uint256,
last_profit_update: uint256,
balance_of_self: uint256,
ts: uint256,
) -> uint256:
unlocked_shares: uint256 = 0
if full_profit_unlock_date > ts:
unlocked_shares = profit_unlocking_rate * (ts - last_profit_update) // MAX_BPS_EXTENDED
//@audit `ts - last_profit_update` is not capped, leading to overestimation
//@audit if ts-last_profit_update is > max_unlock_time
elif full_profit_unlock_date != 0:
unlocked_shares = balance_of_self
return unlocked_shares
def _total_supply(p: PriceParams, ts: uint256) -> uint256:
return p.total_supply - self._unlocked_shares(
p.full_profit_unlock_date,
p.profit_unlocking_rate,
p.last_profit_update,
p.balance_of_self,
ts, //@audit Uses the incorrectly calculated unlocked shares
)

Impact

Excessive Share Unlockingts - last_profit_update could be significantly larger than profit_max_unlock_time, leading to more shares being unlocked than intended.

Incorrect Price Calculation – Since _unlocked_shares directly affects _total_supply, the excessive unlocking skews the price calculation, potentially causing incorrect oracle updates.

Tools Used

Manual Review

Recommendation

A solid fix will be to set unlocked_shares = balance_of_self if ts - last_profit_update exceeds profit_max_unlock_time

Updates

Lead Judging Commences

0xnevi Lead Judge
5 months ago
0xnevi Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.