Open sherlock-admin2 opened 2 months ago
Escalate
As I stated in #107 , there are two issues categorized in the same pool. I know it's same problem which is applied to two different variable but the debt and supply are completely different things. Those issues have completely different impacts on the protocol even the problem is similar.
Escalate
As I stated in #107 , there are two issues categorized in the same pool. I know it's same problem which is applied to two different variable but the debt and supply are completely different things. Those issues have completely different impacts on the protocol even the problem is similar.
You've created a valid escalation!
To remove the escalation from consideration: Delete your comment.
You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.
2 different issues with 2 different impacts. 2 different root cause but similar. This should be separated into two issues Incorrect Supply - 189, 210, 1, 19, 29, 84,127,149, 51, 243, 250, 269, 313, 357, 420, 440, 491, 506. Incorrect Debt - 190, 208, 2, 30 126, 152, 157, 161, 180, 254 ,270, 314, 421, 459.
Some Watsons submitted this together - 52, 473, 138, 272, 444, 469, 503, 504, 516.
I missed some anyone can help add them also. But my point is in line with @DemoreXTess these are two different issues with different impacts hence they should be classified appropriately. Thank you.
I disagree with the escalation.
The Lead Judge correctly duplicated them under the same logical error rule.
If the following issues appear in multiple places, even in different contracts
- Issues with the same logic mistake.
Moreover, the root cause is the same. It is that the functions return share amount
instead of asset amount
.
You might also look at some Watson's who have written two issues and see how the difference is only a few words (for example, #151 and #152).
Planning to reject the escalation and leave the issue as is.
Result: High Has duplicates
KupiaSec
High
Wrong calculation of supply/debt balance of a position, disrupting core system functionalities
Summary
There is an error in the calculation of the supply/debt balance of a position, impacting a wide range of operations across the system, including core lending features.
Vulnerability Detail
PositionBalanceConfiguration
library have 2 methods to provide supply/debt balance of a position as follows:The implementation contains a critical error as it returns the
share amount
rather than theasset amount
held. This issue is evident when the function utilizesindex
, same asself.lastSupplyLiquidityIndex
orself.lastDebtLiquidityIndex
. Each function returnsself.supplyShares
andself.debtShares
, which are share amounts, while the caller expects accurate asset balances. A similar issue occurs when a different index is used, still resulting in an incorrect balance that is significantly lower than the actual balance.Below I provide a sample scenario to check supply balance (
getSupplyBalance
using same liquidity index):position.lastSupplyLiquidtyIndex
=2 RAY
(2e27) (Time passed as the liquidity increased).2 RAY
of assets, it got1 RAY
(2RAY.rayDiv(2RAY)) shares minted.position.getSupplyBalance(2 RAY)
returns1 RAY
while we expect2 RAY
which is correct balance.Below is a foundary PoC to validate one live example: failure to fully repay with type(uint256).max due to balance error. Full script can be found here.
Run the test by
Logs:
Impact
Since these functions are integral to the core pool/position logic and are utilized extensively across the system, the impacts are substantial.
SupplyLogic.executeWithdraw
, withdrawl is processed based on wrong position supply balance which potentially could fail.In
BorrowLogic.executeRepay
, it would failpayback.assets
is not the total debt amountsetBorrwing(reserve.id, false)
becausegetDebtBalance
almost unlikely goes 0, as it can't do full repay// Allows a user to max repay without leaving dust from interest. if (params.amount == type(uint256).max) {
...
}
In
NFTPositionManagerSetter._repay
, wrong balance is used to estimate debt status and refunds.NFTErrorsLib.BalanceMisMatch
becausedebtBalance
is share amount versusrepaid.assets
is asset amountcurrentDebtBalance
will never go 0 because it almost unlikely gets repaid in full, hence refund never happens_handleDebt
would work wrongly due to incorrect balanceif (previousDebtBalance - currentDebtBalance != repaid.assets) { revert NFTErrorsLib.BalanceMisMatch(); }
if (currentDebtBalance == 0 && repaid.assets < params.amount) { asset.safeTransfer(msg.sender, params.amount - repaid.assets); }
// update incentives _handleDebt(address(pool), params.asset, params.tokenId, currentDebtBalance);
emit NFTEventsLib.Repay(params.asset, params.amount, params.tokenId); }
In
CuratedVault.totalAssets
, it returns wrong asset amount.Code Snippet
https://github.com/sherlock-audit/2024-06-new-scope/blob/main/zerolend-one/contracts/core/pool/configuration/PositionBalanceConfiguration.sol#L126-L140
https://github.com/sherlock-audit/2024-06-new-scope/blob/main/zerolend-one/contracts/core/pool/logic/SupplyLogic.sol#L118
https://github.com/sherlock-audit/2024-06-new-scope/blob/main/zerolend-one/contracts/core/pool/logic/BorrowLogic.sol#L126
https://github.com/sherlock-audit/2024-06-new-scope/blob/main/zerolend-one/contracts/core/positions/NFTPositionManagerSetters.sol#L44-L82
https://github.com/sherlock-audit/2024-06-new-scope/blob/main/zerolend-one/contracts/core/positions/NFTPositionManagerSetters.sol#L119-L121
https://github.com/sherlock-audit/2024-06-new-scope/blob/main/zerolend-one/contracts/core/vaults/CuratedVault.sol#L368-L372
Tool used
Manual Review, Foundary
Recommendation
The
getSupplyBalance
andgetDebtBalance
functions need an update to accurately reflect the balance. Referring togetSupplyBalance
andgetDebtBalance
functions fromReserveSuppliesConfiguration
, we can make updates as following: