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 Unlocking – ts - 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
over 1 year ago
0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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

Give us feedback!