sherlock-audit / 2024-09-symmio-v0-8-4-update-contest-judging

0 stars 0 forks source link

safdie - Front-running vulnarebility with the `closedPrice`, `openedPrice`, and `filledAmount` parameters will allow an attacker monitor the mempool and attempt to front-run legitimate transactions in `LibPartyBPositionsActions.sol` #26

Open sherlock-admin3 opened 1 week ago

sherlock-admin3 commented 1 week ago

safdie

Medium

Front-running vulnarebility with the closedPrice, openedPrice, and filledAmount parameters will allow an attacker monitor the mempool and attempt to front-run legitimate transactions in LibPartyBPositionsActions.sol

Summary

In contract LibPartyBPositionsActions.sol is a front-running risk with the closedPrice, openedPrice, and filledAmount parameters, as the contract relies on external inputs without clear on-chain verification mechanisms. This means that an attacker could monitor the mempool and attempt to front-run legitimate transactions, gaining an unfair advantage by executing their transactions before the victim.

Root Cause

Closed price and opened price: If a user places an order to close or open a position at a specific price, a front-runner can observe this transaction in the mempool. The front-runner can submit their own transaction with the same filledAmount but a slightly better closedPrice or openedPrice, ensuring that their transaction gets mined first. By doing this, the front-runner could profit at the expense of the original user. This can lead to loss for the original trader as they may end up executing trades at less favorable prices than intended. https://github.com/sherlock-audit/2024-09-symmio-v0-8-4-update-contest/blob/main/protocol-core/contracts/libraries/LibPartyBPositionsActions.sol#L16-L34 https://github.com/sherlock-audit/2024-09-symmio-v0-8-4-update-contest/blob/main/protocol-core/contracts/libraries/LibPartyBPositionsActions.sol#L36-L175

Filled amount: If a user places a request to close a position with a specific filledAmount, a front-runner can watch for this pending transaction. They could place their own transaction to fill the order with a higher amount before the original transaction is processed. This manipulation allows the front-runner to fill their own order first, potentially benefiting from price movements that result from the larger order being filled.

Internal pre-conditions

  1. A user submits a request to close a position at closedPrice with a specified filledAmount.
  2. The transaction is pending in the mempool.

External pre-conditions

No response

Attack Path

The front-runner observes the transaction and quickly submits their transaction with:

In PoC below an example of how front-running might manifest in the contract methods you've shared. The focus is on how an external actor might exploit the parameters.

Impact

When the front-runner's transaction is mined first, they close their position at a more favorable price. The original user may end up closing their position at a less favorable price due to the price change caused by the front-runner's transaction. This results in a loss for the original user and a profit for the front-runner.

PoC

function fillCloseRequest(uint256 quoteId, uint256 filledAmount, uint256 closedPrice) internal {
    // Assume a malicious front-runner observes this transaction and reacts accordingly

    Quote storage quote = QuoteStorage.layout().quotes[quoteId];

    // Front-runner places a transaction with the same filledAmount but a better closedPrice
    require(quote.quoteStatus == QuoteStatus.CLOSE_PENDING || quote.quoteStatus == QuoteStatus.CANCEL_CLOSE_PENDING,
            "PartyBFacet: Invalid state");

    // Example of a potential front-running situation
    if (quote.positionType == PositionType.LONG) {
        require(closedPrice >= quote.requestedClosePrice, "PartyBFacet: Closed price isn't valid");
    } else {
        require(closedPrice <= quote.requestedClosePrice, "PartyBFacet: Closed price isn't valid");
    }

    // Original user’s transaction continues...
}

Mitigation

  1. Implement a time delay on transaction execution, giving users time to react to unfavorable price movements.
  2. Use oracles to determine the best prices before executing trades, potentially delaying execution until a stable price is confirmed.
  3. Batch transactions together to be executed at once to reduce the chance of individual transactions being targeted.
  4. Implement techniques such as commit-reveal schemes where users must commit to their trades first before revealing the actual parameters.
  5. Introduce random delays in transaction processing to obfuscate the actual transaction timings.