sherlock-audit / 2023-05-perennial-judging

12 stars 9 forks source link

Nyx - New positions can be liquidated instantly #160

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

Nyx

high

New positions can be liquidated instantly

Summary

When opening a new position, the user can be liquidated after one oracle epoch.

Vulnerability Detail

When a user requests to open or close a new position, that position delta sits in a pending state until the next oracle version update, after which it takes effect. If the price volatility happens in the next epoch, the user can be liquidated instantly.

Impact

Unfair liquidations for position owners.

Code Snippet

liquidate.test.ts

it('instant liquidation test', async () => {
    //@audit test
    const POSITION = utils.parseEther('0.0001')
    const { user, userB, collateral, dsu, chainlink } = instanceVars

    const product = await createProduct(instanceVars)
    await depositTo(instanceVars, user, product, utils.parseEther('1000'))

    // Open Position
    await product.connect(user).openMake(POSITION)

    // Settle the product with a new oracle version
    await chainlink.next()
    await chainlink.nextWithPriceModification(price => price.mul(10))
    await product.settle()
    await product.settleAccount(user.address)

    //Liquidate
    expect(await collateral.liquidatable(user.address, product.address)).to.be.true

    await expect(collateral.connect(userB).liquidate(user.address, product.address))
  })

https://github.com/sherlock-audit/2023-05-perennial/blob/main/perennial-mono/packages/perennial/contracts/product/Product.sol#L193-L231

https://github.com/sherlock-audit/2023-05-perennial/blob/main/perennial-mono/packages/perennial/contracts/product/Product.sol#L274-L313

Tool used

Manual Review

Recommendation

When finalizing the position, check liquidation; if the account is liquidatable, revert