Read-Only Reentrancy / Transient-State Oracle Desynchronization
- Name: Read-only reentrancy / transient-state oracle desynchronization
- Category: exploit pattern / reentrancy variant / oracle desynchronization / stale-state pricing
- Summary: Read-only reentrancy is the variant where the attacker does not need to re-enter a victim to mutate its storage directly. Instead, they force some other protocol to read a transient intermediate state while a callback-capable operation is still half-finished. The classic shape is a numerator/denominator mismatch: balances, reserves, or assets and supply, debt, or liabilities have not moved together yet. A lending market, oracle helper, router, liquidation path, or CDP mint engine then treats that mid-transaction snapshot as final truth and extends real value against a state that only exists inside the callback window. The important split is whether the transient read overvalues the attacker’s own position or undervalues someone else’s: Rari’s 2021 ibETH integration, Mai Finance’s patched near miss, Market.xyz, Sentiment, Conic, and EraLend are the
temporary markup -> fake borrow powercousins, while dForce is the sharper reminder that a transiently depressed mark can be just as fatal once liquidation code, settlement discounts, or forced-unwind paths accept the false price as execution truth. - What it is:
- Protocol A performs an operation that briefly leaves its own state internally inconsistent mid-transaction.
- That operation includes a callback-capable edge such as an ETH transfer, token hook, flash-loan callback, or external adapter call.
- During the callback window, Protocol B calls
viewhelpers or price functions against Protocol A and gets a stale-but-valid-looking answer. - Protocol B treats that answer as collateral truth, routing truth, or solvency truth and releases real value.
- The attacker profits not by writing twice into the same storage, but by monetizing a transient read mismatch across protocol boundaries.
- Typical preconditions:
- A callback-capable operation exposes an intermediate state where one part of accounting has updated and another part has not.
- An integrating protocol reads that state onchain during the same transaction for collateral checks, liquidations, routing, or mark-to-market valuation.
- The integrating protocol assumes
viewmeans safe and does not defend against the upstream protocol being mid-transition. - The payout path honors the false mark immediately: borrow stronger assets, withdraw funds, mint rewards, or route against the stale quote.
- The attacker can force the read to happen exactly inside the callback window rather than after final settlement.
- Common vulnerable surfaces:
- onchain wrapper exchange-rate helpers such as
totalAssets()/totalSupply()ortotalETH()/totalSupply() - onchain LP-token or vault-share pricing helpers such as Curve
get_virtual_price()or wrapperassets/sharereaders whose monotonicity assumptions only hold after settlement - lending protocols that accept wrapper assets and price them from live reserve state
- liquidation engines that read pool balances or exchange rates during external unwind flows
- routers or aggregators that trust same-transaction reserve snapshots from callback-capable venues
- any integration that depends on
viewreads from a system known to use reentrancy guards only on mutating entrypoints
- onchain wrapper exchange-rate helpers such as
- Exploit sequence:
- The attacker builds or borrows a position large enough that a transient mark-up will matter.
- They enter a callback-capable path in Protocol A such as
exitPool,withdraw, or another asset-return flow. - Protocol A updates some accounting first — often burning shares or shrinking supply — but has not yet updated reserves, balances, or other matching state.
- The callback fires and returns control to the attacker while that mismatch is live.
- Inside the callback, the attacker makes Protocol B read the inconsistent state from Protocol A.
- Protocol B converts the stale read into fake collateral value, a false liquidation opportunity, a bad route, or another actionable privilege.
- The attacker extracts real assets before Protocol A finishes normalizing its state, either by borrowing against a transient markup or by buying / liquidating someone else’s position against a transient markdown.
- Variants:
- Supply-down / balances-stale — share or LP supply shrinks before reserve balances update, inflating per-share value.
- Balances-down / supply-stale — assets or reserves have already left while LP supply or share counts still look too large, often depressing per-share value and creating false liquidation opportunities.
- Execution-path underpricing — the stale read is only profitable once liquidation, deleveraging, settlement, or closeout code accepts the temporary markdown as executable truth for someone else’s position.
- Balances-down / liability-stale — assets have left but debt, liabilities, or accounting checkpoints still look healthier than reality.
- Cross-module read-only reentrancy — the inconsistency lives in one module, but an oracle or helper in another module turns it into a trusted answer.
- Guarded-write / unguarded-view — mutating functions are locked, but the profitable surface is a
viewintegration that can still observe broken intermediate state.
- Boundary tests that keep this pattern distinct:
- Classify it here when the false mark only exists inside a callback window or other mid-transition state. If the attacker must catch Protocol A after one accounting leg has updated but before the matching leg has settled, the core mistake is transient-state consumption, not generic market printing.
- Classify wrapper- or vault-exchange-rate cases here when the quoted object itself is only false mid-callback. Rari’s ibETH case is the clean reminder that no AMM LP oracle is required: the dangerous read can be an upstream wrapper’s own temporarily inflated
assets/shareortotalETH()/totalSupply()ratio. - Classify it under oracle manipulation when the attacker can leave behind a price that outside observers could still read after the transaction or across blocks. A thin AMM pump, a printable order-book quote, or a stale/frozen feed is still an oracle problem even if liquidation code or a collateral wrapper becomes the payout rail.
- Classify liquidation-path cases here when liquidation is only the monetization rail for a callback-window misread. dForce belongs here because the profitable markdown existed only during Curve’s
remove_liquidity()callback window; once Curve finished settling, the liquidation thesis disappeared. - Classify liquidation-path cases under oracle or liquidation design when the markdown is durable enough that no callback timing is needed. If the attacker can manipulate or freeze a feed and then liquidate after the manipulated price is generally visible, the callback boundary is not doing the decisive work.
- Ask whether quiescent-state replays still work. If the same borrow, liquidation, or withdrawal remains profitable after the upstream protocol fully settles, this note is probably only adjacent context, not the primary classification.
Three read-authority promotions reviewers should not collapse
-
Raw or transitional state is still visible
- A reserve ratio, virtual price, wrapper exchange rate, or assets-per-share number can still be read somewhere during execution.
- That only answers
can someone observe a number right now?It does not yet answer whether the upstream protocol stands behind that number as settled enough for collateral, liquidation, or routing decisions.
-
The upstream protocol publishes one canonical settled-state read object
- A guarded helper, context probe plus valuation helper, delayed snapshot, or other protocol-authored surface answers the stronger question
what exact read object is the upstream system willing to defend as quiescent-state truth for integrations? - This is already a stronger claim than
raw state is readable, but it is still not automatically the same thing asevery downstream consumer may spend against it immediately in every mode.
- A guarded helper, context probe plus valuation helper, delayed snapshot, or other protocol-authored surface answers the stronger question
-
A downstream consumer spends against that published object
- Borrowing, liquidation, deleveraging, collateral toggles, route selection, or sibling-market reserve spending now accept that object as money-good authority.
- This still deserves its own boundary.
The protocol published a safe readis not yet the same thing asthis exact consumer was entitled to mint debt, seize collateral, or route value against it right now.
The recurring review mistake in this family is flattening all three steps into one vague the oracle read worked moment. The sharper question is where the dangerous promotion happened: at raw observation, at publication of a supposed safe surface, or at the later downstream decision to let that surface move money immediately.
What sound design looks like
-
The upstream protocol either publishes a machine-checkable safe-read surface for valuation-critical state or makes unsafe callback-window reads fail closed.
Viewanswers that are only true after settlement should not stay callable during active callback frames. -
Observation, publication, and downstream activation stay distinct on purpose. A protocol can expose raw accounting for local execution, publish one narrower settled-state helper or delayed snapshot for integrations, and still stage which downstream consumers may spend against that published object immediately. safe-read oracle interfaces and Delayed snapshots and same-block quarantine are the sharper positive-design companions for those two design choices.
-
Integrators bind solvency, liquidation, routing, and deleveraging logic to settled-state reads rather than to raw same-transaction reserve, share-price, or exchange-rate helpers whose inputs can diverge mid-transition.
-
Upstream lock state, callback context, or settled-snapshot provenance is part of the oracle interface itself, not undocumented tribal knowledge hidden in blog posts or code comments.
-
The read discipline applies to every path that can spend a false mark, including collateral toggles, liquidations, closeout helpers, keeper flows, and deprecated edge entrypoints rather than only the main borrow path.
-
Safety checks key off execution context, not metadata guesses like
ETHversusWETH, pool-version labels, or wrapper-type branches that can silently route the guard away from the live venue. -
Even after a safe or delayed read surface exists, downstream consumers may still deserve staged activation, caps, or borrow-side quarantine before they treat that surface as full debt or liquidation authority. Collateral-admission lag and borrow-side quarantine is the sharper companion when the dangerous promotion happens after publication rather than at the read surface itself.
-
When no trustworthy same-transaction valuation surface exists, the design admits that fact and forces delayed settled snapshots, caps, or other blast-radius controls rather than pretending a live read is safe enough.
-
The clean target is
no downstream consumer can monetize an upstream intermediate state, whether the temporary distortion is a markup of the attacker’s position or a markdown of someone else’s. -
Detection heuristics:
- Treat
viewconsumers as part of the attack surface whenever upstream state can be read mid-transition. - Ask whether a protocol exposes any point where
balances,assets,reserves,totalSupply,debt, orsharesare updated in separate steps around an external call. - Look for oracle helpers that combine multiple upstream reads which are only safe if taken from a quiescent, fully-settled state.
- Review whether integrators explicitly check upstream reentrancy context before consuming reserve data.
- Be suspicious of protocols that say a mid-transaction state is harmless because
nothing can mutate here; read-only consumers can still monetize it. - Flag liquidation, forced-unwind, and settlement code separately from borrow paths; callback-window underpricing often matters most where the protocol itself converts a temporary markdown into permission to seize or close someone else’s assets.
- Treat
-
Defenses:
- Make critical valuation paths verify that the upstream protocol is not in a re-entrant or mid-transition context before consuming state.
- Apply that protection uniformly to every solvency-changing entrypoint, not just the obvious
deposit,withdraw, orborrowfunctions. Sturdy is the reminder that a deprecated collateral-toggle helper can be just as dangerous if it still changes what counts toward health-factor math. - Treat liquidation and closeout code as first-class oracle consumers, not as downstream bookkeeping. dForce is the reminder that an attacker may not need to overvalue their own collateral at all if a callback-window markdown lets them seize healthy positions at a discount.
- Prefer explicit upstream context checks or vendor-supplied safe-read helpers over brittle heuristics about pool type, token wrappers, or whether a given venue “should” be safe; Conic is the reminder that
ETHversusWETHmetadata can decide whether the safety check runs at all. - Avoid pricing wrapper assets from raw same-transaction reserve reads when upstream accounting can be transiently inconsistent. EraLend is the reminder that even an upstream code comment saying reserves are intentionally still old is enough to make a reserve-based LP oracle unusable during callbacks.
- Prefer oracle constructions that use manipulation-resistant or delayed state rather than immediate callback-window balances.
- Document integration-safe supply functions and state-reading rules explicitly; many losses come from downstream protocols calling the wrong helper at the wrong time.
- Treat cross-protocol
viewcode as security-critical when it gates collateral, liquidation, or withdrawals.
-
Design routing companion worth preserving:
- Safe live read versus delayed settled read — use settled-state read surface discipline when the upstream protocol could realistically have exposed a machine-checkable safe read surface, and pivot to delayed snapshots and same-block quarantine when the stronger design answer is that no same-transaction valuation surface should have been trusted at all.
-
Defensive integration primitives worth preserving:
- Public reentrancy-context probes — Balancer’s own BPT valuation docs explicitly tell downstream protocols to check Vault context on every onchain price evaluation and recommend
VaultReentrancyLib.ensureNotInVaultContext(vault). The key idea is not Balancer-specific math; it is that integrators need a supported way to askis the upstream system mid-transition right now?before trusting reserve or supply reads. - Lock-probing fallbacks when no public context exists — ChainSecurity’s Curve LP postmortem notes that many Curve integrators had no public lock-state view, so the practical workaround was to call a cheap state-changing function such as
withdraw_admin_fees()purely to trip the pool’s reentrancy lock and revert if the pool was already inside a callback window. That is a useful emergency pattern, but it is still second-best to exposing a direct safe-read primitive. - Revert unsafe views, not just unsafe writes — the long-term design lesson from both Balancer’s docs and ChainSecurity’s recommendations is that upstream protocols should either expose lock state or make sensitive
viewhelpers revert while the lock is active.viewdoes not mean harmless if downstream protocols will monetize the answer immediately. - Do not route defenses through metadata heuristics — Conic had the right category of defense, but attached it to an
_isETH()branch that depended on anETHsentinel address while the live Curve v2 pool exposed WETH. If a safe-read guard only runs when token metadata looks the way the integrator expects, then the metadata has become part of the trust boundary.
- Public reentrancy-context probes — Balancer’s own BPT valuation docs explicitly tell downstream protocols to check Vault context on every onchain price evaluation and recommend
Failure-prevention checklist
- Identify every solvency-critical or price-critical read that can occur during an external callback, not just every write that can occur there. If the answer can gate borrow power, liquidation, routing, or withdrawal value, treat the read surface as security-critical.
- Publish one canonical safe-read contract surface for each callback-capable system: either an explicit
ensureNotInContext()/isNotInContext()guard, or a valuation helper that already enforces quiescent-state reads. - Make unsafe valuation helpers fail closed during active callback windows. A stale reserve snapshot that still returns a number is usually more dangerous than a revert.
- Require downstream integrations to prove that all collateral, liquidation, deleveraging, and closeout paths use the guarded read surface rather than raw
getReserves(),getPoolTokens(),get_virtual_price(),totalAssets(), or wrapper exchange-rate helpers. - Apply the same read discipline to edge entrypoints, deprecated toggles, migration helpers, and keeper paths. If a function can change what counts as collateral or can settle another user’s position, it is in scope even if it is not named
borroworwithdraw. - Prefer delayed settled snapshots when an upstream protocol cannot expose a trustworthy same-transaction valuation surface. Some integrations should not read live state at all.
- Keep token-type or pool-type detection out of the safety boundary whenever possible. Safe-read gating should not depend on whether the integrator guessed
ETHversusWETH, Curve v1 versus v2, or any other metadata branch correctly. - Fuzz multi-step state transitions around callbacks with invariant checks on
assets,shares,reserves,debt, and liquidation eligibility. The important property is not justnonReentrant; it isno downstream consumer can monetize an intermediate state. - Monitor production for impossible same-block patterns: reserve or share-price spikes that revert by transaction end, unusual liquidations during withdrawal callbacks, or repeated borrow / liquidate flows against the same upstream venue inside one transaction.
- Put blast-radius controls under integrations anyway: borrow caps, collateral caps, liquidation throttles, and pause paths should assume a safe-read mistake will eventually slip through somewhere.
Audit prompts
- Which upstream calls used in collateral, liquidation, or routing logic can legally run while the upstream system is mid-transition?
- Does the protocol rely on raw reserve balances,
totalSupply,totalAssets, LP virtual price, wrapper exchange rate, or another ratio that can be inconsistent for even one callback frame? - What exact external call opens the observation window: token hook, ETH transfer, flash-loan callback, router callback, strategy adapter, or settlement hook?
- Are any
viewhelpers documented as unsafe during active locks or callbacks, and if so, do integrators actually use the safe alternative everywhere? - Can a temporary markdown of someone else’s collateral be monetized through liquidation logic even if borrow paths are guarded against temporary markups of the attacker’s own collateral?
- Which entrypoints mutate collateral membership, health-factor inputs, or liquidation eligibility without passing through the protocol’s main oracle-validation path?
- Does any defense depend on token metadata, pool-version detection, or special-case wrapper typing rather than on a direct check of upstream execution context?
- If the upstream protocol offers no public lock-state probe, what prevents same-transaction integrations from reading a half-settled state anyway?
- Can the exploit still work after the upstream protocol fully settles? If not, where exactly is the callback-window boundary, and is every monetization path forced to respect it?
- What invariant proves that no same-transaction callback can convert a transient reserve/share mismatch into durable borrow power, liquidation rights, or withdrawal value?
Lessons that should already be standard
-
viewis not a trust guarantee. A read-only answer can still be economically malicious if the system publishing it is halfway through changing its own state. -
Readable now,published as the protocol's defended safe surface, andalready spendable by this downstream consumerare different authority claims. Treat them as separate promotions, not one convenience gradient. -
Reentrancy defenses that only protect writes are incomplete when downstream protocols monetize reads. Unsafe publication is enough.
-
Liquidation paths deserve the same oracle paranoia as borrow paths. A temporary markdown can be just as profitable as a temporary markup once the protocol itself performs the forced sale.
-
Metadata-driven safety checks are fragile security boundaries. If the safe path only runs for the token or pool types the team remembered to special-case, the missing branch becomes the exploit.
-
Upstream protocols own part of their integration safety story. If a system knows some live reads are unsafe during callbacks, it should expose a machine-checkable safe surface or make the unsafe reads revert.
-
Even famous monotonicity assumptions are usually settlement-scoped, not unconditional. Curve’s
get_virtual_price()was widely treated asonly goes up, but Conic and the earlier Curve-LP warnings showed that this property can fail insideremove_liquidity()callback windows when balances and LP supply have not reconverged yet. -
Downstream protocols cannot outsource quiescence assumptions. If collateral math depends on another protocol being settled, the integration has to verify that assumption in code, and then decide separately whether the resulting settled object deserves immediate borrow-side or liquidation authority.
-
Some venues are fundamentally snapshot-only for solvency purposes. When no reliable same-transaction truth exists, delayed pricing is a feature, not a concession.
-
The right question is not merely
can this callback mutate me?butcan this callback make me believe a state that stops being true a few stack frames later? -
High-signal incidents:
- [[../../../incidents/callbacks-reentrancy/rari-capital-ethereum-pool-ibeth-totaleth-work-read-only-reentrancy-drain-2021-05-08|Rari Capital Ethereum Pool ibETH
totalETH()/work()read-only reentrancy drain (2021-05-08)]] — the early integration exemplar: Rari minted and burned REPT against two different ibETH ratios inside Alpha Homora V1’s still-openwork()frame, showing that an upstream wrapper’s own callback-window accounting can become a downstream lossless-pool valuation bug long before later Curve-LP and Balancer cases. - [[../../../incidents/callbacks-reentrancy/beanstalk-basin-wells-getreserves-read-only-reentrancy-near-miss-2023-05-31|Beanstalk Basin Wells
getReserves()read-only reentrancy near miss (2023-05-31)]] — the clean upstream-protocol hardening exemplar: Basin recognized that locking writes was not enough whilegetReserves()still published stale reserve truth during callback windows, so it made the sensitiveviewrevert under active reentrancy before downstream pumps and integrators could spend against it. - [[../../../incidents/callbacks-reentrancy/mai-finance-steth-curve-vaults-get-virtual-price-read-only-reentrancy-near-miss-2022-10-18|Mai Finance stETH Curve vaults
get_virtual_price()read-only reentrancy near miss (2022-10-18)]] — the useful whitehat-preempted CDP exemplar: QiDao’sSCSEMVTandYCSEMVTvaults could have treated Curve’s callback-window LP overvaluation as stablecoin-mint collateral truth, preserving thetemporary markup -> bad-debt issuancecousin before a public drain landed. - QuickSwap Lend stMATIC Curve LP oracle read-only reentrancy exploit (2022-10-24) — the early realized Curve-LP lender exemplar: Beefy-wrapped Curve stMATIC / WMATIC LP collateral inherited callback-window
get_virtual_price()inflation, and Market.xyz turned that temporary overvaluation into realmiMATICborrow capacity inside an isolated market. - ETH Curve vault read-only reentrancy liquidation manipulation (2023-02-09) — the liquidation-path cousin: Curve
remove_liquidity()temporarily depressedget_virtual_price(), dForce markedwstETHCRV-gaugecollateral down in the callback window, and the attacker used that false underpricing to liquidate other users and seize discounted collateral. - Sentiment Balancer BPT read-only reentrancy exploit (2023-04-04) — the clean Balancer-integrator exemplar: Balancer burned a huge BPT position before updating Vault balances, Sentiment read
getPoolTokens()against the already-reduced BPTtotalSupply(), and a temporary accounting mismatch became about $1M of real borrowing power. - collateral-toggle bypass (2023-06-12) — a useful
partial fix still losescousin: Sturdy knew BalancergetRate()was callback-sensitive and had already wrapped most user paths in_validateOracle(), but one unguarded collateral-toggle function still let the attacker use a transient BPT overvaluation to disable and withdraw different collateral. - Conic Finance ETH Omnipool read-only reentrancy exploit (2023-07-21) — the guarded-but-misrouted Curve-LP oracle exemplar: Conic already had a Curve read-only reentrancy defense, but it only activated when a pool appeared to hold the ETH sentinel address; the relevant Curve v2 pool exposed WETH instead, so
CurveLPOracleV2consumed a callback-window LP overvaluation andwithdraw()honored it. - USDC LP oracle read-only reentrancy exploit (2023-07-25) — a strong non-Balancer / non-Curve LP-collateral exemplar: SyncSwap burned LP supply before updating reserves and deliberately exposed a callback with old reserve values still readable, so EraLend overvalued a tiny remaining LP position and let the attacker borrow USDC, then recycle the position through liquidation once reserves normalized.
- [[../../../incidents/callbacks-reentrancy/rari-capital-ethereum-pool-ibeth-totaleth-work-read-only-reentrancy-drain-2021-05-08|Rari Capital Ethereum Pool ibETH
Internal linkages
- Parent pattern: reentrancy.
- Positive-design companion on what the upstream protocol should have exposed: safe-read oracle interfaces.
- Delayed-valuation companion when no safe same-transaction read exists: Delayed snapshots and same-block quarantine.
- Frequent downstream monetization path: lp-token-oracle-mispricing.
- Best early upstream-wrapper integration exemplar in this corpus: rari-capital-ethereum-pool-ibeth-totaleth-work-read-only-reentrancy-drain-2021-05-08.
- Best upstream safe-read hardening exemplar in this corpus: beanstalk-basin-wells-getreserves-read-only-reentrancy-near-miss-2023-05-31.
- Best whitehat pre-exploit Curve-LP / CDP exemplar in this corpus: mai-finance-steth-curve-vaults-get-virtual-price-read-only-reentrancy-near-miss-2022-10-18.
- Best early production Curve-LP lender exemplar in this corpus: market-xyz-quickswap-lend-stmatic-curve-lp-oracle-read-only-reentrancy-2022-10-24.
- Best liquidation-path / transient-underpricing exemplar in this corpus: dforce-wsteth-eth-curve-vault-read-only-reentrancy-liquidation-manipulation-2023-02-09.
- Best Balancer-style exemplar in this corpus: sentiment-balancer-bpt-read-only-reentrancy-2023-04-04.
- Best
partial mitigation missed one pathexemplar: sturdy-finance-balancer-wsteth-weth-read-only-reentrancy-collateral-toggle-bypass-2023-06-12. - Best guarded-but-misrouted Curve-LP oracle exemplar in this corpus: conic-finance-eth-omnipool-read-only-reentrancy-2023-07-21.
- Best non-Balancer / non-Curve LP-collateral exemplar in this corpus: eralend-syncswap-eth-usdc-lp-oracle-read-only-reentrancy-2023-07-25.
Control surface
-
The leverage sits at the seam between a protocol’s callback sequencing and another protocol’s willingness to trust mid-transaction
viewreads. -
The subtle mistake is not just
reentrancy exists; it is assuming that because a callback cannot directly rewrite one protocol’s storage, the state observed inside that callback is safe to price, liquidate, deleverage, or lend against. -
The sharper control question is three-layered: what raw state remained observable, what exact safe or delayed read object the upstream protocol published, and which downstream consumers were still allowed to spend against that object immediately.
-
The time-boundary follow-up matters too: some systems should have published a machine-checkable safe-read surface, while others should have admitted that no safe same-block valuation existed and forced downstream consumers onto delayed settled snapshots instead.
-
The practical split worth preserving is
temporary markup of my own collateralversustemporary markdown of someone else's collateral: the first usually needs seed inventory on the attacker’s side, while the second can turn the protocol’s own liquidation machinery into the monetization rail. -
Sources:
- https://hackmd.io/@sentimentxyz/SJCySo1z2
- https://docs-v2.balancer.fi/concepts/advanced/valuing-bpt/valuing-bpt.html
- https://github.com/balancer/balancer-v2-monorepo/blob/9c1574b7d8c4f5040a016cdf79b9d2cc47364fd9/pkg/pool-utils/contracts/lib/VaultReentrancyLib.sol
- https://sturdyfinance.medium.com/exploit-post-mortem-49261493307a
- https://medium.com/@ConicFinance/post-mortem-eth-and-crvusd-omnipool-exploits-c9c7fa213a3d
- https://www.chainsecurity.com/blog/curve-lp-oracle-manipulation-post-mortem
- https://www.numencyber.com/technical-analysis-of-dforce-networks-5-4-million-attack/
- https://x.com/dForcenet/status/1623904209161830401
- https://x.com/QuickswapDEX/status/1584524584984145922
- https://quillaudits.medium.com/decoding-220k-read-only-reentrancy-exploit-quillaudits-30871d728ad5
- https://polygonscan.com/tx/0xb8efe839da0c89daa763f39f30577dc21937ae351c6f99336a0017e63d387558
- https://rekt.news/eralend-rekt
- https://strawberry.report/eralend-incident/
- https://github.com/syncswap/core-contracts/blob/5285a3a7b2b00ca8b7ffc5ae5ce6f6c6195e4aa7/contracts/pool/classic/SyncSwapClassicPool.sol#L199-L210
-
Last reviewed: 2026-07-28 UTC