Platform: Code4rena
Start Date: 03/05/2023
Pot Size: $60,500 USDC
Total HM: 25
Participants: 114
Period: 8 days
Judge: Picodes
Total Solo HM: 6
Id: 234
League: ETH
Rank: 19/114
Findings: 2
Award: $606.99
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: rvierdiiev
Also found by: J4de, SpicyMeatball, volodya
570.7462 USDC - $570.75
Detailed description of the impact of this finding. User can avoid bankruptcy for his position inside PositionManager.
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept. Whenever user would like to redeem his position, there is a check that position is not bankrupt.
function reedemPositions( RedeemPositionsParams calldata params_ ) external override mayInteract(params_.pool, params_.tokenId) { ... if (_bucketBankruptAfterDeposit(pool, index, position.depositTime)) revert BucketBankrupt(); ...
A user can revive their position (rather than going bankrupt) by creating a new position and transferring its liquidity to the desired position that they want to recover. As you can see that whenever position`s liquidity being moved to another position his positionTime is being rewritten, instead of taking minimun from both of them
function moveLiquidity( MoveLiquidityParams calldata params_ ) external override mayInteract(params_.pool, params_.tokenId) nonReentrant { ... // update position LP state fromPosition.lps -= vars.lpbAmountFrom; toPosition.lps += vars.lpbAmountTo; // update position deposit time to the from bucket deposit time // @audit // toPosition.depositTime = Math.max(vars.depositTime, toPosition.depositTime); toPosition.depositTime = vars.depositTime; emit MoveLiquidity( ownerOf(params_.tokenId), params_.tokenId, params_.fromIndex, params_.toIndex, vars.lpbAmountFrom, vars.lpbAmountTo ); }
Assign minimum deposition time to interacted position
function moveLiquidity( MoveLiquidityParams calldata params_ ) external override mayInteract(params_.pool, params_.tokenId) nonReentrant { Position storage fromPosition = positions[params_.tokenId][params_.fromIndex]; MoveLiquidityLocalVars memory vars; vars.depositTime = fromPosition.depositTime; // handle the case where owner attempts to move liquidity after they've already done so if (vars.depositTime == 0) revert RemovePositionFailed(); // ensure bucketDeposit accounts for accrued interest IPool(params_.pool).updateInterest(); // retrieve info of bucket from which liquidity is moved ( vars.bucketLP, vars.bucketCollateral, vars.bankruptcyTime, vars.bucketDeposit, ) = IPool(params_.pool).bucketInfo(params_.fromIndex); // check that bucket hasn't gone bankrupt since memorialization if (vars.depositTime <= vars.bankruptcyTime) revert BucketBankrupt(); // calculate the max amount of quote tokens that can be moved, given the tracked LP vars.maxQuote = _lpToQuoteToken( vars.bucketLP, vars.bucketCollateral, vars.bucketDeposit, fromPosition.lps, vars.bucketDeposit, _priceAt(params_.fromIndex) ); EnumerableSet.UintSet storage positionIndex = positionIndexes[params_.tokenId]; // remove bucket index from which liquidity is moved from tracked positions if (!positionIndex.remove(params_.fromIndex)) revert RemovePositionFailed(); // update bucket set at which a position has liquidity // slither-disable-next-line unused-return positionIndex.add(params_.toIndex); // move quote tokens in pool ( vars.lpbAmountFrom, vars.lpbAmountTo, ) = IPool(params_.pool).moveQuoteToken( vars.maxQuote, params_.fromIndex, params_.toIndex, params_.expiry ); Position storage toPosition = positions[params_.tokenId][params_.toIndex]; // update position LP state fromPosition.lps -= vars.lpbAmountFrom; toPosition.lps += vars.lpbAmountTo; // update position deposit time to the from bucket deposit time + if(toPosition.depositTime ==0){ + toPosition.depositTime = vars.depositTime; + } else{ + toPosition.depositTime = vars.depositTime < toPosition.depositTime ? vars.depositTime :toPosition.depositTime; + } emit MoveLiquidity( ownerOf(params_.tokenId), params_.tokenId, params_.fromIndex, params_.toIndex, vars.lpbAmountFrom, vars.lpbAmountTo ); }
Timing
#0 - c4-judge
2023-05-18T13:41:46Z
Picodes marked the issue as duplicate of #179
#1 - c4-judge
2023-05-27T16:38:50Z
Picodes marked the issue as satisfactory