Assessment reports>Echelon>High findings>Improper bounds on collateral and liquidation base points
Category: Protocol Risks

Improper bounds on collateral and liquidation base points

High Severity
Medium Impact
Low Likelihood

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 the set_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 of u64 (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 via set_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 and set_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 set liquidation_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.

Zellic © 2024Back to top ↑