Rebalance asset/liability slippage
Description
When a rebalance is performed, there is no guarantee that the asset/liability (A/L) ratio is changed as much as expected, as the A/L checks in the rebalance
functions only verify that the A/L remains above the floor in case of _rebalanceDown
and below the ceiling in the case of _rebalanceUp
. This can be seen in the _validateALRatio
function.
function _validateALRatio(Range.Data storage validRange, uint128 ratioBefore, uint128 ratioAfter, AlValidationMode alMode) internal virtual {
if (alMode == AlValidationMode.LOWER_THAN_BEFORE) {
// Check that the new A/L is not below the floor
// In this mode, the A/L may be above the ceiling still, but should be decreasing
// Note: The A/L may not be strictly decreasing in this mode since the liabilities (in reserve terms) is also
// fluctuating
if (ratioAfter < validRange.floor) revert ALTooLow(ratioBefore, ratioAfter, validRange.floor);
} else {
// Check that the new A/L is not above the ceiling
// In this mode, the A/L may be below the floor still, but should be increasing
// Note: The A/L may not be strictly increasing in this mode since the liabilities (in reserve terms) is also
// fluctuating
if (ratioAfter > validRange.ceiling) revert ALTooHigh(ratioBefore, ratioAfter, validRange.ceiling);
}
}
Impact
The performance of the fund may be impacted as not as much leveraged interest is accumulated and the per-borrower interest rate might be set with the expectation of a certain A/L ratio being reached.
Recommendations
Implement a slippage check for the A/L range that verifies that the A/L has moved in the expected direction and that it is within a margin of the expected A/L.
Remediation
This was remediated in commit d3ed0724↗ by modifying the rebalance functions to accept a params
parameter that contains new members such as minNewAL
and maxNewAL
which enforce the slippage of the A/L rebalance when calling rebalanceDown
or rebalanceUp
.
{
if (alRatioAfter <= alRatioBefore) revert ALTooLow(alRatioBefore, alRatioAfter, alRatioBefore);
if (alRatioAfter < params.minNewAL) revert ALTooLow(alRatioBefore, alRatioAfter, params.minNewAL);
if (alRatioAfter > params.maxNewAL) revert ALTooHigh(alRatioBefore, alRatioAfter, params.maxNewAL);
}