Improper bounds on collateral and liquidation base points
Description
The protocol admin has the ability to update a number of protocol parameters. However, some essential parameters do not have proper bounds checks, which leads to a centralization risk making the protocol require unnecessary trust from users.
The
liquidation_incentive_bps
determines the multiplier applied to the repaid liability to calculate the collateral amount seized. The admin can modify this parameter via theset_liquidation_incentive_bps
function.public entry fun set_liquidation_incentive_bps(manager: &signer, liquidation_incentive_bps: u64) acquires IsolatedLending, Pair { assert!(manager::is_manager(manager), ERR_ISOLATED_LENDING_UNAUTHORIZED); assert!(liquidation_incentive_bps >= BPS_BASE, ERR_ISOLATED_LENDING_INVALID_LIQUIDATION_INCENTIVE_BPS);
This function does not set an upper bound on
liquidation_incentive_bps
, allowing it to be set to a very high value up to the maximum value ofu64
(18446744073709551615).
The
collateral_factor_bps
represents the percentage of the collateral value that can be borrowed against per asset pair. The admin can modify this parameter of the specific asset pair viaset_pair_collateral_factor_bps
.public entry fun set_pair_collateral_factor_bps(manager: &signer, pair_obj: Object<Pair>, collateral_factor_bps: u64) acquires IsolatedLending, Pair { assert!(manager::is_manager(manager), ERR_ISOLATED_LENDING_UNAUTHORIZED); assert!(collateral_factor_bps <= BPS_BASE, ERR_ISOLATED_LENDING_INVALID_COLLATERAL_FACTOR_BPS);
This function does not set a lower bound on
collateral_factor_bps
, allowing it to be set to a very low value, even zero.
Both
set_liquidation_incentive_bps
andset_pair_collateral_factor_bps
check whether it is guaranteed that there is enough collateral available to cover the liquidation bonus at the moment of liquidation, ensuring that the newly setliquidation_incentive_bps
/collateral_factor_bps
is valid.inline fun validate_liquidation_collateral_coverage(collateral_factor_bps: u64, liquidation_incentive_bps: u64) { assert!(collateral_factor_bps * liquidation_incentive_bps <= BPS_BASE * BPS_BASE, ERR_ISOLATED_LENDING_INSUFFICIENT_COLLATERAL_COVERAGE _FOR_LIQUIDATION); }
This check is performed by calling validate_liquidation_collateral_coverage
, which can be bypassed by setting collateral_factor_bps
to zero.
Impact
The protocol admin may take the entire collateral from the borrower by setting collateral_factor_bps
to zero and giving an extremely high value to liquidation_incentive_bps
, then liquidating the positions but repaying only a very small portion of the debt.
Recommendations
Add proper upper/lower bounds to liquidation_incentive_bps
and collateral_factor_bps
. Additionally, consider using a time lock or a governance process to update these parameters.
Remediation
This issue has been acknowledged by Echelon, and a fix was implemented in commit f7ff1ced↗.