Loss: roughly $19.3M to $19.4M in the June 10 exploit, with an additional roughly $3.7M lost in a June 13 replay after UwU’s first oracle patch proved incomplete
Summary: UwU Lend let sUSDe pricing flow through a custom fallback-oracle path that security writeups describe as blending a large set of inputs, several of them derived from manipulable Curve spot prices. Instead of forcing the protocol to rely on a small set of deep, hard-to-move prices, UwU’s oracle composition let a flash-loan-funded attacker drag enough underlying inputs to move the final sUSDe mark. Quill says the oracle used the median of 11 sources and that 5 of those sources were cheaply moveable through Curve; Verichains describes the failing custom provider as sUSDePriceProviderBUniCatch, reached through FallbackOracle, with the exploitable branch flowing through getPrice() -> _getPrices(...) -> _getCrvUsdUSDeEMAInUSD(). The attacker used that underpriced sUSDe mark to borrow too cheaply, then profited again when the mark rebounded and UwU’s liquidation / rehypothecation machinery repriced the same positions upward.
Trigger / entry point:
UwU used an Aave-style oracle stack with a fallback path for assets whose pricing came from custom getters rather than a single strong feed.
Verichains reports that on 2024-04-16 the owner updated the relevant oracle path to 0xd252953818bDf8507643c237877020398FA4B2E8, identified there as sUSDePriceProviderBUniCatch.
The custom getter incorporated Curve-derived price inputs, and Quill notes that UwU read Curve’s get_p() instantaneous spot-style output without smoothing even though that made the price much cheaper to move with flash-liquidity.
Multi-source aggregation did not save the protocol because too many constituent inputs shared the same weak liquidity surface; the attacker did not need to break every source, only enough of them to move the final value UwU honored.
Root cause:
UwU treated source count as if it were the same thing as source independence. In practice, several of the inputs could be pushed with the same flash-loan attack path through Curve pools.
The oracle path used spot-sensitive, low-latency inputs for a solvency-critical asset. That made sUSDe cheap to reprice temporarily relative to the much larger value UwU would lend against it.
UwU also let the manipulated mark feed directly into borrowing, liquidation, and repeated borrow/lend loops, so the exploit was not just bad price data; it was a balance-sheet design that converted temporary quote distortion into durable protocol losses.
The June 13 replay showed the deeper failure was architectural. Replacing one oracle contract without removing the broader weak-input composition left the same attack family reachable.
Exploit path:
The attacker funded Ethereum address 0x841dDf093f5188989fA1524e7B893de64B421f47 and used helper contract 0x21C58d8F816578b1193AEf4683E8c64405A4312E.
Using large flash liquidity — Quill describes roughly 40,000 ETH of flash-loaned capital against pools with about $173M of relevant liquidity — the attacker pushed the Curve-side inputs feeding UwU’s custom sUSDe oracle.
That moved UwU’s sUSDe valuation downward to roughly $0.99, cheap enough to borrow sUSDe against stronger collateral at terms the protocol would not have allowed under an honest mark.
The attacker then reversed the relevant pool pressure so the oracle rebounded to roughly $1.03.
Because UwU let the same manipulated asset price govern liquidation and credit mechanics, the attacker could harvest value from the swing itself: underpriced borrowing on the way down, then liquidation / rehypothecation gains and higher collateral credit on the way back up.
Verichains describes the tail of the exploit as exchanging assets to drive the price back up, liquidating the affected borrowing positions, then depositing the newly revalued sUSDe to borrow more base assets.
By the time the price normalized and UwU paused, the protocol had honored the distorted marks and eaten about $19.4M of losses.
UwU replaced the oracle after the first exploit, but the patch did not fully remove the weak-input path; a second exploit on 2024-06-13 extracted about another $3.7M.
What the attacker needed to be true:
Enough of UwU’s effective sUSDe price inputs had to depend on the same shallow or flash-moveable Curve liquidity.
UwU had to use those inputs quickly enough that flash-loan-funded spot distortion could become a protocol-recognized mark before arbitrage normalized the pools.
Borrowing and liquidation logic had to trust the same manipulated price rather than gating it behind longer smoothing, stale-price rejection, or circuit breakers.
UwU had to keep enough high-quality reserves on hand for a temporarily mispriced sUSDe position to be worth monetizing.
Technical anatomy worth remembering:
This is the many weak sources do not make one strong oracle version of oracle manipulation. The failure was not a single bad feed so much as correlated bad feeds packaged to look robust.
Quill’s description is especially worth preserving: a median of 11 sources still failed because 5 were cheaply manipulable and the protocol used Curve’s unsmoothed get_p() path.
Verichains’ reconstruction preserves the contract-level call path worth remembering: FallbackOracle delegated to a custom IPriceGetter, and the exploitable sUSDePriceProviderBUniCatch branch reached _getCrvUsdUSDeEMAInUSD().
The incident also shows why oracle failures often compound when the manipulated mark controls both entry and cleanup. UwU used the same price surface for borrowing power and liquidation opportunity, so the attacker could profit on both sides of the move.
The June 13 replay matters analytically because it demonstrates incomplete mitigation. Swapping oracle addresses after the first incident was not enough when the core design still admitted spot-sensitive correlated inputs.
Oracle-related contract highlighted by Verichains: 0x9bc6333081266e55d88942e277fc809b485698b9
Updated price-provider address highlighted by Verichains: 0xd252953818bDf8507643c237877020398FA4B2E8
First exploit transaction noted by Verichains: 0xca1bbf3b320662c89232006f1ec6624b56242850f07e0f1dadbe4f69ba0d6ac3
Additional June 10 exploit transactions noted by Verichains: 0xb3f067618ce54bc26a960b660cfc28f9ea0315e2e9a1a855ede1508eb4017376, 0x242a0fb4fde9de0dc2fd42e8db743cbc197ffa2bf6a036ba0bba303df296408b
Second exploit transaction noted by Verichains: 0x9235e0662e230bdfa94f56f4932fd09a95fea17e4b9b44a4f40a59449e216110
Response / mitigation:
UwU paused the protocol after the first exploit and publicly acknowledged the issue.
The team replaced the failing oracle contract, but the follow-up exploit on June 13 showed the patch did not fully remove the manipulable pricing path.
The durable fix for this family is not swap in another custom getter; it is to remove correlated weak inputs, avoid instantaneous spot prices for solvency-critical assets, and force slower or more conservative collateral treatment until a price source is demonstrably depth-backed.
UwU’s advertised many-source oracle diversity hid a shared dependency root: enough of the effective sUSDe price stack still reduced to flash-moveable Curve state that one coordinated pool distortion could move the final mark the protocol used
The exploitable branch was not just wrong median; it was fallback-oracle composition admitted correlated spot-sensitive inputs into solvency truth, so medianization created a false appearance of robustness rather than real economic independence
The protocol then let the same manipulated sUSDe mark govern both entry and cleanup — borrowing power on the way down, liquidation / rehypothecation opportunity on the way back up — which turned a temporary quote distortion into durable reserve loss
The June 13 replay matters as much as the June 10 exploit because it shows incomplete mitigation: swapping one oracle contract did not remove the weak-input composition or the protocol’s willingness to trust that composite immediately
Why the exploit worked
UwU confused source multiplicity with source independence. Verichains and Quill both describe an oracle path where the final sUSDe price was assembled from many components, but several of the decisive legs still drew truth from the same Curve liquidity complex. In practice, the attacker did not need to defeat eleven independent witnesses; they needed to move enough views of the same market state.
The fallback path also admitted the wrong kind of raw material into a solvency-critical price. Quill’s writeup highlights Curve get_p()-style instantaneous spot reads, and Verichains traces the exploitable branch through FallbackOracle -> sUSDePriceProviderBUniCatch.getPrice() -> _getPrices(...) -> _getCrvUsdUSDeEMAInUSD(). Once spot-sensitive or cheaply shifted pool state becomes an accepted ingredient, medianization does not restore safety; it only smooths how the manipulation is packaged.
UwU then granted that composite price too much authority. The manipulated sUSDe mark was not merely displayed or used for soft monitoring; it directly changed what users could borrow, how positions would later be liquidated, and how the attacker could cycle collateral back into fresh borrowing. The same price surface authored both opening leverage and harvesting value from the rebound.
The exploit window was short but sufficient because the protocol consumed these inputs quickly. A flash-loan-funded distortion could move the pools, move the oracle, move borrow terms, and then move liquidation outcomes before deeper markets or slower references reasserted a truer price.
The second exploit proved the problem was architectural rather than one-contract-local. If replacing the provider still leaves correlated weak inputs and fast trust in the resulting composite, the payout rail remains open.
Detection and audit pivots
Decompose every many-source oracle into an independence inventory. Which inputs are actually different trust roots, and which are merely alternate transforms of the same pool state, same quote asset, or same liquidity complex?
Trace how spot-sensitive values enter the final answer. If a solvency-critical composite still consumes unsmoothed get_p()-style reads or similarly low-latency DEX state, reviewers should assume flash-liquidity can test that path.
Follow the entire authority chain from oracle publication to reserve loss: pool distortion -> fallback getter -> final asset mark -> borrow allowance -> liquidation path -> rehypothecation / reborrow. A composite oracle is only as safe as the downstream actions it can authorize immediately.
Review replay resistance after emergency patches. If the first postmortem says we swapped the oracle contract, ask whether the new path truly changed the independence roots, smoothing model, and borrow-side authority — or only renamed the same risk.
Inspect fallback paths as first-class price systems rather than backup code. When fallback logic can publish the number that lending and liquidation consume, it deserves the same scrutiny as the nominal primary oracle.
Failure-prevention checklist
Count independent truth roots, not raw source count. Median or average logic should only aggregate feeds that remain meaningfully separate under stress.
Exclude flash-moveable spot reads from solvency-critical composite or fallback paths unless they are heavily bounded, delayed, or demoted to degraded-mode signals.
Treat fallback getters as production oracle systems with their own unit tests, attack simulations, and architecture review; custom backup path is not a safe category by itself.
Keep borrow authority and liquidation authority narrower than raw oracle freshness when the price object depends on wrappers, composites, or correlated venue data.
Add protocol-local brakes around composite price changes: debt ceilings, collateral-factor haircuts, rate-of-change clamps, and temporary borrow disablement when one composite leg diverges sharply.
Test shared-root manipulations explicitly. If one Curve distortion can move enough constituent inputs to shift the final median, the system does not yet have real defense in depth.
After a first oracle incident, quarantine the replacement path with reduced caps and tighter rights until live behavior proves the new composition is economically harder to move.
Separate emergency patching from trust restoration. A new oracle address should not inherit full-size balance-sheet authority on the same assumption set that just failed.
Audit prompts
How many inputs in this composite oracle are genuinely independent once reduced to liquidity venue, quote asset, and manipulation path rather than contract count?
Which exact functions admit spot-sensitive pool state into the published solvency object, and what smoothing, delay, or cap stands between that state and borrowing power?
If one composite leg or one pool complex is distorted for a single block or a few minutes, what maximum borrow, liquidation, or reborrow rights can the protocol grant before a slower reference overrides it?
Does the same price surface govern both opening leverage and monetizing the cleanup path, allowing attackers to profit on both the down-leg and rebound?
After an oracle hotfix, what independent evidence shows the new path changed the underlying trust roots instead of just changing implementation details?
Would a fallback-path failure be caught by monitoring that focuses mainly on the nominal primary oracle, or is the true money-authoring branch effectively unobserved until loss appears?
Which inputs can a flash-loan attacker move together with one capital loop, and how many such jointly moveable inputs are enough to shift the final published price?
What degraded mode activates if independence collapses — slower pricing, lower collateral factors, borrow pause, or some other local refusal to honor the full composite?
Lessons that should already be standard
Many weak sources do not make one strong oracle if they collapse onto the same manipulation surface.
Medianization is not independence. A final price built from correlated inputs can still be a single-point failure wearing eleven masks.
Fallback logic is part of the main security boundary whenever lending or liquidation can consume its output.
Solvency-critical wrappers and composites deserve slower trust and tighter local brakes than simple deep-market spot assets.
Emergency oracle patches should launch under quarantine, because the first replacement often still reflects the same mistaken trust model.
If the same manipulated price can improve entry terms and later improve liquidation or reborrow terms, the protocol has given one price surface too much balance-sheet authority.
The right question is not how many feeds are there? but how many economically distinct things must an attacker move before the protocol believes a lie?
Why this incident matters
It is a strong oracle-manipulation exemplar for the median / aggregator design failure branch rather than the usual single-pool or single-TWAP story.
The note preserves a useful distinction: a protocol can fail even when it has many sources if those sources are economically dependent on the same pool complex.
It also sits between Bonq and Mango in the corpus: not a permissionless oracle report like Bonq, not perp-PnL inflation like Mango, but a solvency-critical asset price built from too many weak spot-sensitive legs.
The leverage sat in oracle composition, not just a single feed: which sources counted, how independent they really were, whether get_p()-style spot reads were allowed into collateral truth, and whether borrow / liquidation logic trusted that composite price immediately.
UwU did not merely choose the wrong oracle. It built an oracle whose apparent diversity hid shared liquidity risk, then let that synthetic consensus govern real reserve outflows.
The healthier control object would have bound full borrowing and liquidation authority to a minimum set of genuinely independent price roots, then failed closed or shifted onto a delayed conservative valuation object when that independence degraded into several views of the same flash-moveable Curve state.