Maker can close position without checking utilization rate.
Summary
A maker can close his position and increase the utilization rate above the allowed level.
Vulnerability Detail
When the product owner creates a product market, he sets the utilization buffer to limit the utilization rate to a certain level. This is necessary to prevent potential issues that could arise when utilization gets too high, such as liquidity crunches or funding rate spikes (if using JumpRateUtilizationCurve).
function updateUtilizationBuffer(UFixed18 newUtilizationBuffer) external onlyProductOwner settleProduct {
if (newUtilizationBuffer.gt(UFixed18Lib.ONE)) revert ParamProviderInvalidParamValue();
_utilizationBuffer.store(newUtilizationBuffer);
emit UtilizationBufferUpdated(newUtilizationBuffer, _productVersion());
}
However, when a maker closes his position, the utilization level check is not applied. It means that the maker can close his position and drive the utilization rate higher than the safe level (1 - utilizationBuffer). This will lead to operational issues when takers cannot open positions anymore or face a jump in funding rate.
Also, when calculating the max redeem amount to withdraw from the BalancedVault, the utilization level with the buffer is not considered. It can lead to a redemption that raises the utilization rate to 1.
Add maxUtilizationInvariant to Product.closeMakeFor function and consider the utilizationBuffer when calculating the max redeem amount in BalancedVault._maxRedeemAtEpoch function.
ast3ros
medium
Maker can close position without checking utilization rate.
Summary
A maker can close his position and increase the utilization rate above the allowed level.
Vulnerability Detail
When the product owner creates a product market, he sets the utilization buffer to limit the utilization rate to a certain level. This is necessary to prevent potential issues that could arise when utilization gets too high, such as liquidity crunches or funding rate spikes (if using JumpRateUtilizationCurve).
https://github.com/sherlock-audit/2023-05-perennial/blob/main/perennial-mono/packages/perennial/contracts/product/UParamProvider.sol#L249-L253
The utilization level check is implemented in the
maxUtilizationInvariant
modifierhttps://github.com/sherlock-audit/2023-05-perennial/blob/main/perennial-mono/packages/perennial/contracts/product/Product.sol#L547-L556
However, when a maker closes his position, the utilization level check is not applied. It means that the maker can close his position and drive the utilization rate higher than the safe level (1 - utilizationBuffer). This will lead to operational issues when takers cannot open positions anymore or face a jump in funding rate.
Also, when calculating the max redeem amount to withdraw from the
BalancedVault
, the utilization level with the buffer is not considered. It can lead to a redemption that raises the utilization rate to 1.https://github.com/sherlock-audit/2023-05-perennial/blob/main/perennial-mono/packages/perennial-vaults/contracts/balanced/BalancedVault.sol#L669-L670
Impact
The utilization rate can exceed the buffer level set by the product owner. The product market will face liquidity and funding issues.
Code Snippet
https://github.com/sherlock-audit/2023-05-perennial/blob/main/perennial-mono/packages/perennial/contracts/product/UParamProvider.sol#L249-L253 https://github.com/sherlock-audit/2023-05-perennial/blob/main/perennial-mono/packages/perennial/contracts/product/Product.sol#L547-L556 https://github.com/sherlock-audit/2023-05-perennial/blob/main/perennial-mono/packages/perennial-vaults/contracts/balanced/BalancedVault.sol#L669-L670
Tool used
Manual Review
Recommendation
Add
maxUtilizationInvariant
toProduct.closeMakeFor
function and consider theutilizationBuffer
when calculating the max redeem amount inBalancedVault._maxRedeemAtEpoch
function.Duplicate of #75