Closed sherlock-admin closed 1 year ago
Lead Watson comment:
looks to be invalid as kicking with manipulated LUP is guarded by kick deposit concept. I.e. it focuses on a surface that is covered by design. One can argue that it’s met only partially, but the bottom line is that’s a known vector that is alleviated by design itself.
Sponsor comment:
Correct, #74 is Invalid
branch_indigo
medium
Malicious users can manipulate spot LUP to kick borrower's loan, causing borrowers penalized with more debts
Summary
Spot Lup(lowest utilization price) can be manipulated and a borrower's account health is evaluated based on spot Lup.
Vulnerability Detail
When a borrower's account health is evaluated, spot Lup price is used. To kick an account, Pool.sol
kick()
is invoked which calls KickerActions.sol, which under the hood calls internal_kick()
where account collateralization is evaluated.As seen from above, before
_isCollateralized()
, the current states ofdeposits_
andpoolState_.debt
is assessed to calculated spotkickResult_.lup
which is used as the price for collateralization.Since states of
deposits_
is updated every transaction when there is a change of quote tokens andpoolState
reflectspoolBalances
which is updated every transaction when there is a change of debt, this means thatkickResult_.lup
can be manipulated with a transaction causing a healthy borrower to be kicked.( Note that new borrow debt fromdrawDebt()
is stored inpoolBalances
and then carried through memorypoolState
without a delay in_accruePoolInterest()
at the beginning ofkick()
.)For example, a malicious user can take on large loans to lower spot LUP prices to allow some high-leveraged borrowers to be undercollateralized. In the same transaction, the malicious user can kick the borrowers who will be instantly punished with 90-day interest and wait for auctions to start.
Impact
High-leveraged borrowers can be unfairly kicked due to spot LUP manipulation, penalized and set up for auctions.
This is different from accounts kicked due to normal market activities or accumulated interests. And when the pool liquidity is low, malicious users have better shots to target specific borrowers and manipulate spot LUPs.
Code Snippet
https://github.com/ajna-finance/ajna-core/blob/e3632f6d0b196fb1bf1e59c05fb85daf357f2386/src/libraries/helpers/PoolHelper.sol#L164
https://github.com/ajna-finance/ajna-core/blob/e3632f6d0b196fb1bf1e59c05fb85daf357f2386/src/libraries/external/KickerActions.sol#L385-L392
Tool used
Manual Review
Recommendation
Consider not using calculated
kickResult._lup
in_isCollateralized()
. Evaluate a borrower's collateralization based on a delayed stored LUP instead of spot LUP. The delayed LUP is similar to Uniswap v3's observation, which can be written to storage at the beginning of the next block. timestamp. This mitigates such attacks so that the manipulated spot price cannot be accessed in the same transaction in_isCollateralized()
.