How SyncSwap V2 Handles Read-Only Reentrancy

How SyncSwap V2 Handles Read-Only Reentrancy


SyncSwap V2 addresses read-only reentrancy by updating pool state before external callbacks and exposing its reentrancy status so dependent contracts can refuse reads during an active operation.

The Syncswap site is the exchange interface for accessing its pools and routing trades.

When choosing between a legacy V1 pool and a V2 pool for a price-sensitive integration, choose V2. The feature most users never notice is not a trading control but a small contract-level signal that tells another protocol whether the pool is currently inside a state-changing call.

Why a read-only call can still be dangerous

SyncSwap is a modular automated market maker on networks including zkSync Era, where pools expose balances, reserves, prices and LP-token values to other contracts. Those reads are marked view, but “read-only” does not mean “safe at every moment.”

The problem appears when a pool sends tokens or invokes a callback before finishing its own accounting. A receiving contract can use that callback to ask the pool for a value such as reserves or virtual price. The call changes nothing, yet it may observe one half of the operation: LP supply has changed while reserves still show the old amount, or token balances have moved while a cached invariant has not.

A lending market that values SyncSwap LP tokens is the concrete case. During a withdrawal, an attacker could arrange for the lending market to read the LP token’s value while the pool was temporarily inconsistent, borrow against the inflated number, and let the withdrawal finish afterward. Zero Knowledge Proofs and zkSync Era’s settlement model do not remove this composability risk; it comes from the order of EVM calls inside one transaction.

What V2 changes in the call sequence

The important V2 change is the position of the accounting update. In the V2 pool flow, the contract calculates the operation, updates its reserve state with the post-operation balances, and only then transfers output tokens or invokes the callback. That ordering means a callback does not get the old reserve snapshot simply because the pool has not returned from the function yet.

V2 pool contracts also inherit a reentrancy guard whose status is publicly readable through reentrantStatus. The normal value indicates that the pool is available; the entered value indicates that a guarded operation is in progress. A lending adapter can check that status before trusting a price, and can fail closed if the check occurs during a callback.

This is the feature’s real use. It does not make every price accurate, and it does not stop an ordinary market move. It gives a dependent contract a cheap way to distinguish a normal read from a read made while SyncSwap is halfway through a state transition.

How to use the protection in an integration

The safest sequence is short, but each step matters:

  1. Resolve the pool through the relevant Pool Master or approved factory, rather than trusting a pool name supplied by a user.
  2. Call poolVersion() and require the V2 value before treating the pool as an oracle source.
  3. Read reentrantStatus() and reject the operation unless the pool is in its idle state.
  4. Read the price, reserves or virtual price from that same verified pool, with your own freshness and deviation limits.
  5. Keep the lending, collateral or liquidation decision fail-closed if any read reverts or the pool reports an active operation.

For a normal trader, this happens behind the router. A MetaMask Wallet user mainly needs the correct network, token approval and slippage setting. The integration burden belongs to the application that uses SyncSwap data to make another financial decision.

The edge case: V1 pools change the answer

V1 pools remain usable for swaps, but they are not the right source for an oracle. SyncSwap’s own technical documentation distinguishes them from V2 pools on this point: V1 pools cannot be used for oracles because their older accounting path can expose state that is unsafe to consume during nested execution.

That distinction matters when a route contains both generations. A router may complete a trade through a V1 pool without trouble, while a lending protocol, vault or liquidation engine separately reads that pool as if it were a V2 oracle. The transaction can succeed and the integration can still be wrong.

V2 also does not remove standard AMM risks. A thin pool can be moved by a large trade, a cached price can be stale, and a poorly designed adapter can ignore token decimals or accepted pool types. Read-only reentrancy is one failure mode, not a complete oracle policy.

FAQ

Does V2 make every SyncSwap price safe?

No. It addresses inconsistent reads during pool execution. You still need liquidity, freshness, deviation and asset-validation checks.

What should a lending protocol read first?

Verify the pool and its V2 version, check reentrantStatus(), then read the selected price or reserve value.

Can a V1 pool be used for trading?

Yes, but its reserves should not be treated as an oracle input for collateral, liquidation or share valuation.

Report Page