_validateSolvency function may fail to accurately determine a user's solvency if the solvency check is bypassed or miscalculated. This function relies on the _checkSolvencyAtTick function to determine the user's solvency at specific ticks.
// Check the user's solvency at the fast tick; revert if not solvent
bool solventAtFast = _checkSolvencyAtTick(
user,
positionIdList,
currentTick,
fastOracleTick,
buffer
);
if (!solventAtFast) revert Errors.NotEnoughCollateral();
// If one of the ticks is too stale, we fall back to the more conservative tick, i.e, the user must be solvent at both the fast and slow oracle ticks.
if (Math.abs(int256(fastOracleTick) - slowOracleTick) > MAX_SLOW_FAST_DELTA)
if (!_checkSolvencyAtTick(user, positionIdList, currentTick, slowOracleTick, buffer))
revert Errors.NotEnoughCollateral();
}
If the solvency check is bypassed or miscalculated, the _validateSolvency function may incorrectly determine a user's solvency.
Root Cause
The _validateSolvency function relies on the _checkSolvencyAtTick function to determine a user's solvency at specific ticks (fast and slow oracle ticks).
The solvency check is performed at the fast oracle tick first, and if the delta between the fast and slow oracle ticks exceeds MAX_SLOW_FAST_DELTA, the solvency is also checked at the slow oracle tick.
bool solventAtFast = _checkSolvencyAtTick(
user,
positionIdList,
currentTick,
fastOracleTick,
buffer
);
if (!solventAtFast) revert Errors.NotEnoughCollateral();
if (Math.abs(int256(fastOracleTick) - slowOracleTick) > MAX_SLOW_FAST_DELTA)
if (!_checkSolvencyAtTick(user, positionIdList, currentTick, slowOracleTick, buffer))
revert Errors.NotEnoughCollateral();
If the _checkSolvencyAtTick function fails to accurately determine a user's solvency based on their collateral balance and the current market conditions, it could lead to the solvency check being bypassed.
Additionally, if the fast and slow oracle ticks can be manipulated or the MAX_SLOW_FAST_DELTA threshold is set inappropriately, it could allow insolvent users to pass the solvency check.
Impact
Insolvent users may be able to gain an unfair advantage by taking positions they cannot fully collateralize, potentially leading to liquidations and loss of funds for other users.
Proof of Concept
Assume a user, Alice, wants to mint an option position while being insolvent.
Alice's collateral balance is insufficient to cover the collateral requirement for the option position she intends to mint.
Alice calls the mintOptions function in the PanopticPool contract, which internally calls the _validateSolvency function to check her solvency before allowing the mint.
Inside the _validateSolvency function, the following steps occur:
The fast oracle tick is computed using PanopticMath.computeMedianObservedPrice.
The slow oracle tick is computed based on the SLOW_ORACLE_UNISWAP_MODE flag.
The _checkSolvencyAtTick function is called with the fast oracle tick to check Alice's solvency.
Scenario 1: Bypassing the solvency check
Assume the _checkSolvencyAtTick function is implemented incorrectly and always returns true, regardless of Alice's actual solvency.
In this case, even though Alice is insolvent, the solventAtFast variable will be set to true.
The _validateSolvency function will not revert, allowing Alice to proceed with minting the option position.
Scenario 2: Manipulating the oracle ticks
Assume the fast and slow oracle ticks can be manipulated by an attacker.
The attacker manipulates the fast oracle tick to a value that makes Alice appear solvent, even though she is actually insolvent.
If the delta between the manipulated fast oracle tick and the slow oracle tick does not exceed MAX_SLOW_FAST_DELTA, the solvency check at the slow oracle tick will be skipped.
As a result, Alice will pass the solvency check and be allowed to mint the option position.
Assume the MAX_SLOW_FAST_DELTA threshold is set to an inappropriately high value.
Even if the fast and slow oracle ticks are significantly different and Alice is insolvent, the delta between the ticks may not exceed the high threshold.
Consequently, the solvency check at the slow oracle tick will be skipped, allowing Alice to mint the option position while being insolvent.
In all three scenarios, Alice, an insolvent user, is able to mint an option position, violating the expected behavior of the _validateSolvency function.
If Alice's position is later liquidated due to her insolvency, it could lead to financial losses for the protocol and potentially impact other users who may have their positions liquidated as well.
Tools Used
Manual review, VS Code
Recommended Mitigation
The values of the fast and slow oracle ticks should be carefully chosen and validated to prevent manipulation or exploitation.
// ...
bool solventAtFast = _checkSolvencyAtTick(
user,
positionIdList,
currentTick,
fastOracleTick,
buffer
);
if (!solventAtFast) revert Errors.NotEnoughCollateral();
// Check solvency at the slow tick if the delta exceeds the threshold
if (Math.abs(int256(fastOracleTick) - slowOracleTick) > MAX_SLOW_FAST_DELTA) {
bool solventAtSlow = _checkSolvencyAtTick(user, positionIdList, currentTick, slowOracleTick, buffer);
if (!solventAtSlow) revert Errors.NotEnoughCollateral();
}
// Additional checks and validations...
// ...
}
Protect against manipulation of the fast and slow oracle ticks, using secure and reliable price oracles.
Set appropriate values for the MAX_SLOW_FAST_DELTA threshold to maintain the effectiveness of the solvency checks.
Lines of code
https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/PanopticPool.sol#L932-L946 https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/PanopticPool.sol#L880-L946
Vulnerability details
Issue Description
_validateSolvency function may fail to accurately determine a user's solvency if the solvency check is bypassed or miscalculated. This function relies on the _checkSolvencyAtTick function to determine the user's solvency at specific ticks.
File: PanopticPool.sol#L933-L945
If the solvency check is bypassed or miscalculated, the
_validateSolvency
function may incorrectly determine a user's solvency.Root Cause
The
_validateSolvency
function relies on the_checkSolvencyAtTick
function to determine a user's solvency at specific ticks (fast and slow oracle ticks).The solvency check is performed at the fast oracle tick first, and if the delta between the fast and slow oracle ticks exceeds
MAX_SLOW_FAST_DELTA
, the solvency is also checked at the slow oracle tick.If the
_checkSolvencyAtTick
function fails to accurately determine a user's solvency based on their collateral balance and the current market conditions, it could lead to the solvency check being bypassed.Additionally, if the fast and slow oracle ticks can be manipulated or the
MAX_SLOW_FAST_DELTA
threshold is set inappropriately, it could allow insolvent users to pass the solvency check.Impact
Insolvent users may be able to gain an unfair advantage by taking positions they cannot fully collateralize, potentially leading to liquidations and loss of funds for other users.
Proof of Concept
mintOptions
function in the PanopticPool contract, which internally calls the_validateSolvency
function to check her solvency before allowing the mint._validateSolvency
function, the following steps occur:PanopticMath.computeMedianObservedPrice
.SLOW_ORACLE_UNISWAP_MODE
flag._checkSolvencyAtTick
function is called with the fast oracle tick to check Alice's solvency._checkSolvencyAtTick
function is implemented incorrectly and always returnstrue
, regardless of Alice's actual solvency.solventAtFast
variable will be set totrue
._validateSolvency
function will not revert, allowing Alice to proceed with minting the option position.MAX_SLOW_FAST_DELTA
, the solvency check at the slow oracle tick will be skipped.MAX_SLOW_FAST_DELTA
thresholdMAX_SLOW_FAST_DELTA
threshold is set to an inappropriately high value._validateSolvency
function.Tools Used
Manual review, VS Code
Recommended Mitigation
The values of the fast and slow oracle ticks should be carefully chosen and validated to prevent manipulation or exploitation.
MAX_SLOW_FAST_DELTA
threshold to maintain the effectiveness of the solvency checks.Assessed type
Invalid Validation