Rujira FIN Exploit: CCL Skew Math Costs $200K
Originally published at Rujira FIN Exploit: CCL Skew Math Costs $200K On the evening of Tuesday, 10 November 2026, someone found a way to make money from the liquidity providers on Rujira Trade, the order book that runs
Originally published at Rujira FIN Exploit: CCL Skew Math Costs $200K
On the evening of Tuesday, 10 November 2026, someone found a way to make money from the liquidity providers on Rujira Trade, the order book that runs as a CosmWasm application on THORChain. Rujira says an attacker "exploited an issue with the CCL skew calculations", which let them unbalance existing BTC/USDC Custom Concentrated Liquidity (CCL) positions. The estimated loss is about $200,000: roughly $175,000 from positions run by Liquidy Finance and roughly $25,000 from other users.
Rujira has said all losses will be reimbursed. THORChain node operators halted the CosmWasm app layer, and the team is preparing an upgraded FIN contract that removes the skew parameter entirely. This is the second FIN incident in about six weeks, which makes it worth a closer look at what a "skew" knob is and why pricing code inside a market maker is such a sensitive place for bugs.
What Happened
Rujira's first update, posted on X on 11 November, describes the sequence in plain terms. Suspicious activity on Rujira Trade caused "a sharp price spike in the BTC/USDC market", followed by "a surge in trading activity across the orderbook". The team's investigation tied this to the skew calculations used by CCL ranges.
DefiLlama's hacks database lists the incident on 11 November with the same $200,000 figure, classifies it as a protocol logic issue and labels the technique a swap logic flaw. No attacker address or transaction hash has been published by Rujira or by the trackers we checked, so we do not name any here.
Timeline
- Tuesday 10 November, evening: abnormal activity, a sharp BTC/USDC price spike and heavy order book trading on Rujira Trade.
- 11 November: Rujira confirms the exploit, gives the $200K estimate and its split, says losses will be fully reimbursed and that CosmWasm is halted. It initially expects recovery to take one to two days.
- 12 November: a second update says the upgraded FIN contract is "almost ready". It removes the skew parameter, adds fixes "to stabilise Custom Concentrated Liquidity" and restores users' CCL positions to compensate them. Rujira now aims to resume the app layer next week, after an audit of the changes and new monitoring are in place.
Background: How CCL Ranges Work
Rujira Trade is an on-chain order book. CCL lets a user turn a pile of base and quote assets into an automated market-making strategy that lives inside the same FIN contract as ordinary limit orders. According to Rujira's integration docs, each range is defined by a handful of parameters:
-
lowandhigh: the price band. Abovehighthe position is all quote (USDC); belowlowit is all base (BTC). -
spread: the gap between the range's internal price and its best bid and ask, which is the profit per round trip. -
fee: the part of that spread taken out as claimable yield. -
skew: the shape of liquidity inside the band. The docs describe it as a "distribution slope", valid between -2 and 2, and tell integrators to use"0"unless they are deliberately building an advanced strategy.
With skew = 0 liquidity is spread evenly. A non-zero value moves more of the position toward the centre of the band or toward its edges. Rujira's strategy docs give the intent: for a stable pair you might pack liquidity near parity, and for a volatile pair like BTC/USDC you might overweight the edges so you sell more BTC near the top of the range and buy more near the bottom.
That is a useful feature, but notice what it implies. The contract is no longer quoting from a simple formula. Every time the price moves, the range has to recompute how much it offers at each price level, and the quotes it publishes are what takers trade against.
The Root Cause: Liquidity Shape Math That Could Be Gamed
Rujira has not published a full post-mortem, so we will stick to what it has said: the attacker exploited the skew calculations and used them to imbalance existing BTC/USDC ranges. The fix is to remove the skew parameter rather than patch it.
That combination tells us a few things.
- The flaw sat in pricing, not in access control. Nobody stole a key or bypassed an owner check. The attacker traded against positions that were quoting prices the contract computed.
- The attack needed market movement. The price spike and surge of trades fit a pattern where the attacker pushes the market, causes ranges to reprice using the faulty skew curve, and then trades back against quotes that are worse for the LP than a correct curve would allow.
- The losers were the liquidity providers. Most of the loss came from one market maker's ranges, the rest from ordinary users. The protocol's own balance sheet was not the target; the LPs' inventory was.
An earlier warning about the same model
FailSafe, which Rujira names as its audit partner, has published an audit report for FIN v2.1.1 on its website. One medium-severity finding in that report, marked resolved, is titled "Linear SCL skew misprices positive-skew ranges and enables systematic LP extraction". It describes a linear weight function that was asymmetric around the range midpoint, so positive skew pushed liquidity in opposite directions on the ask and bid sides, and warns that "sophisticated takers can detect this systematic misplacement and route flow" through the misweighted side.
We cannot confirm that the November exploit used that exact issue, and Rujira has not said so. But the finding shows the category of risk clearly: when a liquidity shape is configurable, a small error in the curve becomes a price that a taker can repeatedly hit.
A simplified illustration
The snippet below is simplified illustrative Rust, not Rujira's code. It shows the property a range should keep after any fill: the value of what it holds, measured at a fair reference price, should not fall by more than the spread it was paid.
// Simplified illustration, not Rujira's code.
fn check_fill(before: &Range, after: &Range, ref_price: Decimal) -> StdResult<()> {
let value_before = before.base * ref_price + before.quote;
let value_after = after.base * ref_price + after.quote;
// A correct range sells above and buys below the reference price,
// so a fill should never leave it worse off than this tolerance.
let tolerance = value_before * Decimal::permille(1);
if value_after + tolerance < value_before {
return Err(StdError::generic_err("range lost value on fill"));
}
Ok(())
}
A real implementation needs a robust reference price that the attacker cannot move in the same transaction, which is exactly the hard part. The point is that a curve which can be pushed into selling low and buying high should fail a test like this long before it reaches mainnet.
Why This Is Hard to Get Right
Concentrated liquidity math has repeatedly hurt protocols because three things interact:
- Rounding and discretisation. Ranges are cut into price slices or ticks. Small rounding choices at each slice add up when an attacker forces many repricings.
- Path dependence. If a range's state after moving up then down is not the same as before, a round trip can leak value. Order books with many small fills create many round trips.
-
Parameter space. Every extra knob, such as skew, multiplies the cases to test. A curve can be correct at
skew = 0and wrong atskew = 1.5.
We saw a related pattern in the ACryptoS depositMulti vault exploit, where valuing a two-token position with only one token's numbers let attackers mint cheap shares, and in the Premia v3 empty option pool exploit, where edge-case pool states broke pricing assumptions.
Lessons for Builders
Fuzz the pricing curve, not just the entry points. Generate random ranges across the full parameter space, apply random sequences of fills and price moves, and assert that the LP never ends a round trip with less value than it started with, apart from the spread it earned.
Treat every resolved audit finding as a regression test. If an auditor shows a curve can be gamed, the fix should come with a property test that would catch any return of the same shape of bug, including in later versions of the math.
Ship advanced knobs behind limits. Rujira's own docs told integrators to keep skew at zero. A new pricing feature can launch with caps on position size or on the allowed skew range until it has real trading history.
Monitor for value leaving LPs, not just the contract. Here the protocol's reserves were not drained directly; liquidity providers were. Alerts on unusual LP losses per block, or on sudden one-sided fills, can catch this kind of attack in minutes. Rujira's plan for continuous monitoring and a withdrawal-slowing system called Gleipnir is aimed at exactly that gap, much like the rate limit that capped losses in the Arcus Perps subaccount exploit.
Have a clean pause. The ability to halt the CosmWasm layer without stopping THORChain's base layer kept the incident to one market and gave the team time to plan a fix.
What Users Should Know
Rujira says all losses will be reimbursed and that the upgraded FIN contract restores affected CCL positions. The app layer is paused, so trading, lending and range management are unavailable until node operators resume it, which Rujira currently targets for next week. Follow only official Rujira channels for updates and ignore unsolicited "refund" or "claim" links. This article is technical commentary, not financial advice.
Sources
- Rujira incident update on X (11 Nov): description of the exploit, loss estimate and split, CosmWasm halt
- Rujira recovery update on X (12 Nov): removal of the skew parameter, position restoration, audit and monitoring plans
- DefiLlama: Rujira AMM Strategies: hack entry, classification and amount
- Rujira docs: Rujira Trade and CCL: range parameters and skew validation
- Rujira docs: Strategies: intended behaviour of skew
- FailSafe audit report, Rujira FIN v2.1.1: earlier finding on skew mispricing
Closing Thoughts
The Rujira loss was modest next to this month's larger incidents, but the lesson travels well. When a contract quotes prices for its users, any error in the quoting math is a standing offer to whoever finds it first, and every extra parameter widens the search space. Removing skew is the safest short-term fix; bringing it back will need invariant tests that prove LPs cannot be traded into a loss. If you are building an AMM, order book or vault with custom liquidity curves, talk to our team or check our audit pricing to have your pricing invariants reviewed before the market tests them.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.