Open sherlock-admin opened 1 year ago
part of PR https://github.com/ajna-finance/contracts/pull/894 that change kickWithDeposit
functionality
https://github.com/ajna-finance/contracts/pull/894/files#diff-54056532b4b7aac8940fbec13725e98ceceb358bef02e1285edad2741dff83bdR363
part of PR ajna-finance/contracts#894 that change
kickWithDeposit
functionality https://github.com/ajna-finance/contracts/pull/894/files#diff-54056532b4b7aac8940fbec13725e98ceceb358bef02e1285edad2741dff83bdR363
Fix looks good, _kick()
is the last operation in kick()
and lenderKick()
(which is the new version of kickWithDeposit()
), and LUP is calculated in _kick()
after all the changes off final structures.
hyh
high
LUP is not recalculated after adding kicking penalty to pool's debt, so kick() updates the pool state with an outdated LUP
Summary
_kick() first calculates LUP, then adds kicking penalty, so the LUP returned without recalculation doesn't include the penalty and this way is outdated whenever it is not zero.
Vulnerability Detail
kick() and kickWithDeposit() (when deposit doesn't have any excess over the needed bond) returns _kick() calculated LUP, which is generally higher then real one being calculated before kicking penalty was added to the total debt.
Impact
kick() is one of the base frequently used operations, so the state of the pool will be frequently enough updated with incorrect LUP and
EMA of LUP * t0 debt
internal accounting variable be systematically biased, which leads to incorrect interest rate dynamics of the pool.There is no low-probability prerequisites and the impact is a bias in interest rate calculations, so setting the severity to be high.
Code Snippet
kick() updates the
poolState
with _kick() returnedresult.lup
:https://github.com/sherlock-audit/2023-04-ajna/blob/main/ajna-core/src/base/Pool.sol#L277-L313
https://github.com/sherlock-audit/2023-04-ajna/blob/main/ajna-core/src/libraries/external/KickerActions.sol#L115-L134
In _kick() kicking penalty is added to the total debt of the pool:
https://github.com/sherlock-audit/2023-04-ajna/blob/main/ajna-core/src/libraries/external/KickerActions.sol#L438-L446
While the function calculates LUP before that (for _isCollateralized() check) and does not recalculate it after the penalty was added:
https://github.com/sherlock-audit/2023-04-ajna/blob/main/ajna-core/src/libraries/external/KickerActions.sol#L364-L442
kickWithDeposit() returns kick() calculated `kickResult.lup
(i.e. before kick penalty) whenever
vars.amountToDebitFromDeposit <= kickResult_.amountToCoverBond`:https://github.com/sherlock-audit/2023-04-ajna/blob/main/ajna-core/src/libraries/external/KickerActions.sol#L190-L216
Tool used
Manual Review
Recommendation
Consider using initial LUP for _isCollateralized() check in kick() as `additionalDebt` is zero in plain kick() case, and calculating the final LUP at the end of _kick().
Consider refactoring kickWithDeposit(): for example, calculating the LUP therein with the corresponding
additionalDebt_
after _kick() call, and adding the flag to _kick() call to indicate that LUP calculation isn't needed.