Skip to content

Latest commit

 

History

History
60 lines (34 loc) · 1.77 KB

File metadata and controls

60 lines (34 loc) · 1.77 KB

Clean Hemp Barracuda

High

Irreversible Order State on Fee Handling Failure

Summary

looking at the Manager _raiseKeeper Fee function, it uses controller. chargeFee to pull fees from the user's account. If chargeFee fails (e.g., insufficient funds), the entire transaction reverts. But the order is already marked as spent, so the user can't retry. This could lock funds permanently, which is a critical problem.

If _raiseKeeperFee fails (e.g., due to insufficient user funds), the order is marked as isSpent = true, but the fee is not charged. This permanently locks the order, preventing retries.

https://github.com/sherlock-audit/2025-01-perennial-v2-4-update/blob/main/perennial-v2/packages/periphery/contracts/TriggerOrders/Manager.sol#L186

Root Cause

Code Reference:

function executeOrder(...) external {
    // ... marks order as spent BEFORE fee handling ...
    order.isSpent = true; // ❌ State changed before fee transfer
    _handleKeeperFee(...); // May revert due to insufficient funds
}

Internal Pre-conditions

No response

External Pre-conditions

No response

Attack Path

Scenario:

  1. User Action: Alice places an order with maxFee = 5 DSU.
  2. Keeper Execution: Bob spends gas to execute the order.
  3. Failure: Alice’s account has only 3 DSU, causing _raiseKeeperFee to revert.
  4. Result: Order is marked isSpent, but Alice cannot retry.

Impact

  • Funds Locked: Users cannot retry failed orders, losing access to their collateral.
  • Denial-of-Service: Attackers can exploit this to lock legitimate users’ orders.

PoC

No response

Mitigation

  • Mark orders as spent after successful fee handling.
  • Use a temporary state to track execution progress.