DEV Community

Cover image for Kamino Lend's $3 Billion TWAP Promise That Doesn't Apply When It Matters
Kim Brandwijk
Kim Brandwijk

Posted on

Kamino Lend's $3 Billion TWAP Promise That Doesn't Apply When It Matters

Kamino Finance tells users their protocol is "protected from flash loans/flash crashes, as dramatic short term price changes are rejected." Their community managers reassure worried users that "TWAP bands are designed to catch abnormal wicks." Their marketing highlights four rounds of formal verification.

None of this applies to liquidation — the one operation where it matters most.

What TWAP Is Supposed to Do

Time-weighted average price (TWAP) smooths out transient price spikes. In a lending protocol, TWAP protects against a scenario every crypto user fears: a brief flash crash triggers a liquidation, the price recovers minutes later, and your collateral is gone forever. You were solvent the entire time — you just got caught in a wick.

Kamino built a full TWAP validation system for exactly this purpose. Every reserve has a configurable maxTwapDivergenceBps tolerance — 10% for SOL, 3% for USDC, 1.5% for PRIME. When the spot price diverges from the TWAP beyond this threshold, the system flags the price as unreliable and blocks the operation.

Across 403 K-Lend reserves holding $3.09 billion in TVL, 402 have TWAP actively configured. The admin clearly intended this protection to cover the platform.

Where It Breaks

K-Lend uses a bitmask system called PriceStatusFlags to track which oracle validations have passed. Different operations require different flags.

Borrowing requires ALL_CHECKS — all six validation flags, including TWAP_CHECKED:

ALL_CHECKS:         0b00111111 (63)
Enter fullscreen mode Exit fullscreen mode

Liquidation requires only LIQUIDATION_CHECKS — three of the six flags. TWAP_CHECKED is not among them:

LIQUIDATION_CHECKS: 0b00100011 (35)
Enter fullscreen mode Exit fullscreen mode

That's it. Three missing bits. The TWAP check runs during refresh_reserve, sets its flag if the price is within tolerance, and if the flag isn't set... borrowing fails. Liquidation doesn't care. Liquidation never looks at that bit.

The entire TWAP infrastructure — the tolerance function, the per-reserve configuration, the flag propagation — exists in the codebase and is fully functional. It just isn't wired into the one code path where users actually lose money.

October 10, 2025: The Day It Was Exploited

On October 10, 2025, SOL dropped 14% in under an hour — from $207 to $177 — following Trump's tariff announcement. Kamino's own post-mortem documents $20M in collateral liquidated across 8,168 events affecting 1,700 wallets.

The post-mortem touts "zero bad debt" and an "orderly response." It never mentions TWAP.

The 14% drop exceeded the mainnet SOL reserve's 10% TWAP tolerance. This means borrowing was blocked during the crash — the TWAP system correctly identified the price as unreliable. But liquidation proceeded without checking.

On-chain data tells the story. Of the 9,121 total liquidation events, 8,168 (89.5%) — representing $16.9M in collateral — fired during the single hour when SOL was actively crashing. Liquidation bots were executing against real-time oracle prices plummeting through $190, $180, $177 while the TWAP was still lagging near $200+.

Consider a user with 1,000 SOL collateral and $146,550 in USDC debt. At the TWAP-lagged price of $200, their LTV is 73.3% — healthy, well below the 75% liquidation threshold. At the flash-crash spot price of $177, their LTV jumps to 82.8% — liquidated. Their position was solvent by the metric TWAP was designed to validate. They lost their collateral anyway.

A conservative estimate based on the 11.5% premature liquidation window: ~$1.08M in premature WSOL liquidations from this single event.

"By Design"

When this finding was reported through responsible disclosure, Kamino's response was that the TWAP omission on liquidation is intentional — that TWAP is meant to protect the platform from bad debt, not to protect users from premature liquidation.

Let that sink in. The protocol's documentation tells users they're protected from flash crashes. The community managers tell users TWAP bands catch abnormal wicks. The admin configured TWAP tolerances on 99.3% of TVL. And the protocol's position is: this protection was never meant to help you.

The Documentation Says Otherwise

Kamino's own docs:

"TWAPs and EWMAs are resistant to price manipulations"

"The protocol is protected from flash loans/flash crashes, as dramatic short term price changes are rejected."

In a community Q&A compiled from Kamino's Discord and Telegram, a user asked whether a momentary depeg — "like a millisecond to 0.5/sol" — would trigger liquidation on their Multiply position. The answer, attributed to Kamino core contributors:

"No, there are multiple backstops and TWAP implementations in place to prevent scam wicks from causing issues. In the event of massive abnormal wicks, TWAP bands are designed to catch them."

Users are sizing their collateral buffers and leverage ratios based on this assurance. A user who maintains a 70% LTV instead of 65% because they trust the TWAP protection is carrying $3.09 billion worth of positions into a crash with less margin than they think they have. The protection they were told exists is not enforced where it matters most.

The Fix Is Two Lines of Code

Adding TWAP validation to liquidation is a two-line change:

pub const LIQUIDATION_CHECKS: PriceStatusFlags = PriceStatusFlags::PRICE_LOADED
    .union(PriceStatusFlags::PRICE_AGE_CHECKED)
+   .union(PriceStatusFlags::TWAP_CHECKED)
+   .union(PriceStatusFlags::TWAP_AGE_CHECKED)
    .union(PriceStatusFlags::PRICE_USAGE_ALLOWED);
Enter fullscreen mode Exit fullscreen mode

If Kamino genuinely needs liquidation to proceed during sustained crashes (a reasonable concern for protocol solvency), the answer is a wider liquidation-specific tolerance — say, 3x the borrowing tolerance. That still blocks flash-crash exploitation while allowing legitimate liquidations during confirmed downtrends.

The current implementation offers no middle ground: full TWAP on borrowing, zero TWAP on liquidation.

The Formal Verification Gap

Kamino's fourth formal verification by OtterSec (October 2025) covers deposit, withdraw, borrow, and repay — "mathematically proves that the smart contract code for core functions operates exactly as intended and cannot put a healthy user position at risk."

Liquidation was not among the formally verified functions.

The borrowing path correctly enforces TWAP, as the verification would confirm. The liquidation path skips it. The gap between "verified" and "unverified" code paths is exactly where this vulnerability lives.

Formal verification is a powerful tool, but it's only as good as its scope. When the scope excludes the one operation that permanently takes user funds, the verification certificate becomes a marketing asset rather than a security guarantee.

Industry Standard: This Is a Solved Problem

Aave V3 implements a PriceOracleSentinel that introduces a grace period for liquidations when oracle health is uncertain — explicitly restricting liquidation during price instability.

In March 2026, a 2.85% oracle misconfiguration on Aave triggered $21.7M in wrongful liquidations of healthy positions, requiring DAO treasury compensation. If 2.85% causes $21.7M in damage on Aave, a 10–14% flash crash on Kamino without TWAP protection has proportionally greater impact across $3.09B in TVL.

A 2022 Code4rena audit of Hubble Protocol recommended: "condition all state changing actions, including liquidations, on the current price being within a threshold of the TWAP one." This is established security guidance, not a novel suggestion.

What Users Should Know

If you have positions on Kamino Lend:

  • TWAP does not protect you from liquidation during flash crashes. Your collateral can be seized at a transient spot price that the protocol's own TWAP system would have flagged as unreliable.

  • Your effective liquidation buffer is thinner than you think. If you're sizing your LTV based on the assumption that TWAP catches scam wicks before liquidation, you need a wider margin. The protection exists for borrowing but not for the operation that takes your money.

  • This has already happened. $16.9M in collateral was seized during a single hour on October 10, 2025, against spot prices that diverged 10–14% from the TWAP. An estimated $1.08M of that was premature — positions that were healthy at the TWAP price but liquidated at the flash-crash price.

  • The protocol considers this working as intended. There are no plans to fix it. Kamino's position is that TWAP protects the platform from bad debt, not users from premature liquidation.

The Bigger Picture

DeFi protocols have a responsibility gap between what they document and what they implement. When a protocol tells users they're protected from flash crashes, configures that protection on 99.3% of assets, builds an entire engineering infrastructure for it, formally verifies the paths where it works, and then omits it from the one path where users actually lose money — that's not a design decision. That's a broken promise.

The $3.09 billion sitting in TWAP-enabled reserves belongs to users who were told their positions are protected. They deserve to know the protection has a gap the size of a liquidation.


The author independently verified all on-chain data referenced in this post using Flipside Crypto's indexed Solana data and direct getProgramAccounts queries against Solana mainnet. The bitmask logic was reproduced in a standalone Rust test that compiles and passes with zero dependencies. All source code references are to the public K-Lend repository at github.com/Kamino-Finance/klend.

Top comments (0)