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

Governance Parameter Feedback Amplification Vulnerability

Summary

The Curve Storage Proofs protocol contains a structural vulnerability in the relationship between two governance-controlled parameters: max_price_increment and max_v2_duration. While each parameter has individual validation bounds, their combined effect creates a multiplicative relationship that can lead to excessive price distortion. This vulnerability enables a governance attacker to make seemingly reasonable parameter adjustments that, when combined, create extreme price movements that undermine the protocol's security model and price stability guarantees.

Vulnerability Details

The vulnerability stems from the independent validation of two parameters that have a multiplicative effect on price behavior:

  1. max_price_increment - Controls price change rate per second with an extremely wide validation range:

@external
def set_max_price_increment(_max_price_increment: uint256):
access_control._check_role(access_control.DEFAULT_ADMIN_ROLE, msg.sender)
assert 10**8 <= _max_price_increment and _max_price_increment <= 10**18
self.max_price_increment = _max_price_increment
  1. max_v2_duration - Controls the maximum extrapolation periods:

@external
def set_max_v2_duration(_max_v2_duration: uint256):
access_control._check_role(access_control.DEFAULT_ADMIN_ROLE, msg.sender)
assert _max_v2_duration <= MAX_V2_DURATION
self.max_v2_duration = _max_v2_duration

These parameters interact in price calculation:

# In _obtain_price_params
number_of_periods: uint256 = min(
(parameters_ts - params.last_profit_update) // period,
self.max_v2_duration,
)
# In _smoothed_price
max_change: uint256 = (
self.max_price_increment * (block.timestamp - self.last_update) * last_price // 10**18
)

Root Cause:
The root cause is the lack of validation for the relationship between these parameters. The contract enforces individual bounds but not their combined effect, allowing parameter combinations that violate the protocol's security model.

Exploitation Conditions:

  • Attacker gains DEFAULT_ADMIN_ROLE privileges

  • Proposes a reasonable-seeming increase to max_price_increment (e.g., from 10^10 to 10^12)

  • In a separate proposal, suggests an increase to max_v2_duration

  • Once both parameters are updated, the combined effect allows for price manipulation significantly beyond intended bounds

Impact

Financial Impact:
If both parameters are set to midpoint of their allowed ranges:

  • Price movement potential increases by ~20-50x compared to default values

  • During market volatility, this enables price distortions of 5-10x normal magnitude

  • Arbitrage opportunity: ~100,000 per event in a $10M liquidity pool

  • Could trigger cascading liquidations in dependent protocols

This calculation assumes:

  • Default max_price_increment of 10^10 increased to 10^12

  • Default max_v2_duration of 30 increased to 100

  • Combined amplification: ~333x normal impact

  • $10M liquidity in affected pools

User Impact:

  • Users relying on oracle prices face unexpected, rapid price movements

  • Liquidations could occur at prices far from market reality

  • StableSwap pools using the oracle could experience dramatic imbalances

Systemic Implications:

  • Undermines the reliability of the oracle for all integrated systems

  • Creates potential for governance manipulation through seemingly innocuous changes

  • Could trigger widespread liquidations in lending markets using the oracle

This vulnerability is classified as MEDIUM severity because:

  1. It requires governance capture (high barrier to exploitation)

  2. The potential impact is significant if successfully exploited

  3. It represents a structural flaw in parameter validation

  4. It undermines core security assumptions

Tools Used

  • Code analysis of governance parameter controls

  • Mathematical modeling of parameter interaction effects

  • Combinatorial parameter testing

  • Governance process analysis

  • Impact assessment across varying liquidity conditions

Recommendations

Immediate Mitigations:

  1. Implement relationship validation between parameters:

@external
def set_max_price_increment(_max_price_increment: uint256):
access_control._check_role(access_control.DEFAULT_ADMIN_ROLE, msg.sender)
assert 10**8 <= _max_price_increment and _max_price_increment <= 10**18
# Add parameter relationship validation
assert _max_price_increment * self.max_v2_duration <= COMBINED_SECURITY_THRESHOLD
self.max_price_increment = _max_price_increment
log SetMaxPriceIncrement(_max_price_increment)
  1. Narrow the permitted parameter ranges significantly:

assert 10**9 <= _max_price_increment and _max_price_increment <= 10**11

Long-term Fixes:

  1. Implement a composite parameter that controls both aspects:

@external
def set_price_security_parameters(_max_increment: uint256, _max_duration: uint256):
access_control._check_role(access_control.DEFAULT_ADMIN_ROLE, msg.sender)
# Validate individual parameters
assert 10**8 <= _max_increment and _max_increment <= 10**12
assert _max_duration <= MAX_V2_DURATION
# Validate relationship
assert _max_increment * _max_duration <= SECURITY_THRESHOLD
self.max_price_increment = _max_increment
self.max_v2_duration = _max_duration
log SetPriceSecurityParameters(_max_increment, _max_duration)
  1. Add time delay for significant parameter changes with monitoring period:

@external
def propose_parameter_change(_max_increment: uint256, _max_duration: uint256):
access_control._check_role(access_control.DEFAULT_ADMIN_ROLE, msg.sender)
self.proposed_max_increment = _max_increment
self.proposed_max_duration = _max_duration
self.proposal_time = block.timestamp
log ParameterChangeProposed(_max_increment, _max_duration)
@external
def apply_parameter_change():
access_control._check_role(access_control.DEFAULT_ADMIN_ROLE, msg.sender)
assert block.timestamp >= self.proposal_time + PARAMETER_CHANGE_DELAY
self.max_price_increment = self.proposed_max_increment
self.max_v2_duration = self.proposed_max_duration
log ParameterChangeApplied(self.max_price_increment, self.max_v2_duration)
Updates

Lead Judging Commences

0xnevi Lead Judge
3 months ago
0xnevi Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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