Skip to content
This repository has been archived by the owner on Jan 7, 2024. It is now read-only.

rvierdiiev - PartyBFacetImpl.openPosition can open position that is not solvent #106

Closed
sherlock-admin opened this issue Jul 3, 2023 · 0 comments
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A valid Medium severity issue Reward A payout will be made for this issue

Comments

@sherlock-admin
Copy link
Contributor

sherlock-admin commented Jul 3, 2023

rvierdiiev

high

PartyBFacetImpl.openPosition can open position that is not solvent

Summary

PartyBFacetImpl.openPosition can open position that is not solvent. This is because it checks solvency based on original locked values, but they can be adjusted if partyB price is not same as quote price.

Vulnerability Detail

When qoute is open, then user provides price, that he would like to get. Also his provided lockedValues are stored to quote. Then his pending locking balance is increased with locked values.
However partyB price can be not same as provided by partyA. Because of that, locked values that back this position can be scaled.

When position is going to be open, then check is done, that it will not make any party insolvent. This check is done before locked values rescaling.

https://github.com/sherlock-audit/2023-06-symmetrical/blob/main/symmio-core/contracts/libraries/LibSolvency.sol#L31-L44

                Quote storage quote = QuoteStorage.layout().quotes[quoteId];
        int256 partyBAvailableBalance = LibAccount.partyBAvailableBalance(
            upnlSig.upnlPartyB,
            quote.partyB,
            quote.partyA
        );
        int256 partyAAvailableBalance = LibAccount.partyAAvailableBalance(
            upnlSig.upnlPartyA,
            quote.partyA
        );


        uint256 lockedAmount;
        uint256 lockedMM;
        if (quote.orderType == OrderType.LIMIT) {
            lockedAmount =
                (filledAmount * (quote.lockedValues.cva + quote.lockedValues.lf)) /
                quote.quantity;
            lockedMM = (filledAmount * quote.lockedValues.mm) / quote.quantity;
        } else {
            lockedAmount = quote.lockedValues.cva + quote.lockedValues.lf;
            lockedMM = quote.lockedValues.mm;
        }


        partyAAvailableBalance -= int256(lockedAmount);
        partyBAvailableBalance -= int256(lockedAmount);

As you can see quote.lockedValues are used to determine solvency.
But this quote.lockedValues are original one(set when quote is created) and it can be changed later(if price of partyB is not same as quote price). They can be increased for example. In this case solvency check will show that partyA is solvent and open position. After that partyA already can be liquidatable.

This is because solvency check should be done after rescaling of quote's locked values.

Impact

PartyBFacetImpl.openPosition can open position that is not solvent

Code Snippet

Provided above

Tool used

Manual Review

Recommendation

Solvency check should be done after rescaling of quote's locked values.

Duplicate of #225

@github-actions github-actions bot added High A valid High severity issue Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label labels Jul 10, 2023
@sherlock-admin2 sherlock-admin2 added Medium A valid Medium severity issue Reward A payout will be made for this issue and removed High A valid High severity issue labels Jul 26, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A valid Medium severity issue Reward A payout will be made for this issue
Projects
None yet
Development

No branches or pull requests

2 participants