Skip to content

CurrencyReserves sync() can be overwritten — settlement manipulation vector #1069

Open

Description

@angguntrie3-lgtm

hey, noticed that sync() can be called multiple times within a single transaction with no access control. Each call overwrites the previous currency and reserves:

function syncCurrencyAndReserves(Currency currency, uint256 value) internal {
    assembly ("memory-safe") {
        tstore(CURRENCY_SLOT, and(currency, 0xffffffffffffffffffffffffffffffffffffffff))
        tstore(RESERVES_OF_SLOT, value)
    }
}

In _settle(), the paid amount is computed as reservesNow - reservesBefore. If sync() is called again between take() and settle(), the reserves snapshot is overwritten, potentially manipulating the settlement amount.

While NonzeroDeltaCount provides a safety net, the unrestricted sync() combined with transient storage creates a complex attack surface.

Is this a known design trade-off? Or should sync() be restricted?

Activity

  1. linear-code commented on Aug 20, 2026

    @linear-code
  2. angguntrie3-lgtm commented on Aug 21, 2026

    @angguntrie3-lgtm
    Author

    thanks for tracking this internally. Let me know if you need any additional details or PoC.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions