Worked example · 2021-09
Vee Finance oracle manipulation — Avalanche — 2021-09-21
Summary
Vee Finance was an Avalanche-based leveraged-trading and lending protocol that launched on 2021-09-14 and reached ~$300M TVL within roughly a week. Its leveraged-trading flow priced collateral and trade-output amounts using a single-source oracle that read prices from Pangolin — Avalanche's leading DEX at the time and effectively the only on-chain venue with non-trivial liquidity for many of the long-tail Avalanche-C-chain assets Vee Finance supported. The oracle's design was explicitly thresholded: it refreshed the cached price whenever the live Pangolin pool price diverged by more than 3% from the cached value, which produced a clear and exploitable target shape — move the pool by just over 3%, and the oracle would adopt the new price as canonical.
On 2021-09-21, an attacker funded ~27 ETH from Tornado Cash, bridged to Avalanche, and deployed contracts that (a) created several new Pangolin trading pairs against attacker-controlled tokens and supplied liquidity to set the initial mid-price, (b) opened leveraged-trade orders on Vee Finance against those pairs, and (c) traded inside the manipulated Pangolin pools to push the oracle-input price across Vee Finance's 3% refresh threshold, causing Vee Finance to consume the manipulated price as collateral and trade-output reference. The protocol's slippage check, which was supposed to reject trades whose output deviated meaningfully from the expected swap amount, failed in two ways simultaneously: (1) the oracle price was not normalised for token decimals when computing the expected output, so the comparison was numerically wrong before manipulation was even applied; and (2) the slippage check was further defeated by inconsistencies in how the cToken-style collateral wrapper resolved its underlying token across different code paths, allowing an attacker-supplied wrapper to return one underlying for price lookup and another for swap execution. BlockSec's post-event analysis foregrounded the cToken-validation flaw as the real root cause, framing the oracle component as an enabler rather than the proximate failure; SlowMist's, Halborn's, and Vee Finance's own post-mortems foregrounded the Pangolin-single-source oracle. Both framings describe the same chain of events, and both belong in T9.001 — the oracle-design surface and the trust-boundary-mismatch in the cToken wrapper compose to produce the extraction, and removing either layer would have broken the attack.
The attacker withdrew 8,804.7 ETH and 213.93 BTC, bridged out via 0x and standard Avalanche-Ethereum bridges, and laundered through a combination of ParaSwap, Curve.fi, and the Ren BTC bridge. No portion was returned. Vee Finance suspended the affected contracts on 2021-09-20 (the platform side detected the incident slightly before the public timestamp), engaged SlowMist for forensic support, and published a multi-stage compensation plan over 2021-09-24 through 2021-10-31 that committed the protocol to bearing the loss and reimbursing depositors via a token-denominated compensation pool funded by ongoing platform revenue.
Timeline (UTC)
| When | Event | OAK ref |
|---|---|---|
| 2021-09-14 | Vee Finance mainnet launch on Avalanche; liquidity-mining program live the same day | (standing T9.001 surface deployed) |
| 2021-09-14 to 2021-09-20 | TVL grows to ~$300M; standing oracle surface (single-source Pangolin price feed, 3% refresh threshold, decimals-unaware slippage check) is in production for ~7 days | (standing T9.001 surface) |
| early Sep 2021 | Zabu Finance (separate Avalanche protocol) exploited for ~$3.2M via a different vector; first widely-reported Avalanche DeFi exploit, narrative-context for Vee Finance one week later | (cohort context, not same Technique) |
| 2021-09-20 ~T-8min | Attacker address 0xeeeE…95ba receives ~27 ETH from Tornado Cash |
(T9.001 setup — capital sourcing) |
| 2021-09-20 (same window) | Attacker bridges ETH to Avalanche; deploys exploit contracts; some early deploys revert on gas | T9.001 setup |
| 2021-09-20 to 2021-09-21 | Attacker creates new Pangolin trading pairs (QI/WETH.e, XAVA/WETH.e, LINK.e/WETH.e, and others reported across forensic write-ups) and supplies liquidity to set initial mid-prices | T9.001 oracle-input setup |
| 2021-09-21 (per cycle) | Attacker opens leveraged-trade orders on Vee Finance against the attacker-seeded pairs, passing an attacker-controlled cToken wrapper whose getUnderlying() and price-oracle-side getUnderlyingPrice() resolve to different underlying tokens |
T9.001 setup (trust-boundary mismatch) |
| 2021-09-21 (per cycle) | Attacker trades inside the Pangolin pools, pushing the price across the 3% refresh threshold; Vee Finance's oracle adopts the manipulated price as canonical | T9.001 oracle move |
| 2021-09-21 (per cycle) | Vee Finance computes the expected swap output using the manipulated price, with no decimal-normalisation, producing an artificially low expected-output figure; the slippage check passes for a swap that pays out far more than fair | T9.001 extraction (slippage bypass) |
| 2021-09-21 (per cycle) | Attacker repeats the order-and-trade cycle across the seeded pairs; net extraction reaches 8,804.7 ETH + 213.93 BTC | T9.001 chained extraction |
| 2021-09-20 (post-event) | Vee Finance team detects the incident; suspends smart contracts (stablecoin sector: withdrawals/repayments only; crypto sector: all trading orders suspended) | (defender response) |
| 2021-09-21 onward | Attacker bridges proceeds out via 0x; converts ~213 ETH to BTC through ParaSwap / Curve.fi / Ren; fragments BTC across multiple addresses | (T7-class outflow; out of T9 scope) |
| 2021-09-24 | Vee Finance posts $500,000 bounty for attacker identification; offers white-hat return path | (post-event) |
| 2021-09-25 to 2021-09-30 | SlowMist publishes root-cause analysis foregrounding single-source Pangolin oracle and decimals-unaware slippage check; BlockSec publishes dissenting analysis foregrounding fake-cToken validation gap; Halborn publishes a third write-up reconciling both views | (forensic record) |
| 2021-09-28 | Vee Finance publishes restart plan | (post-event) |
| 2021-10-02 to 2021-10-31 | Compensation pool details finalised; community vote (143 of 466 eligible voters) chooses "tokens as they are" by 68%; pool opens 2021-10-31 with AVAX, WBTC, WETH, LINK, USDT and is funded by ongoing platform revenue on a monthly basis | (defender response — protocol-funded reimbursement) |
What defenders observed
- Pre-event (oracle-design layer, Avalanche-ecosystem-specific): Vee Finance's price oracle had a single input source — Pangolin — and refreshed on a 3% deviation trigger. On Avalanche in September 2021, this was not an unusual design choice: Pangolin was the leading DEX on the chain, and for many of the long-tail C-chain assets Vee Finance supported, Pangolin was the only venue with non-trivial liquidity. The oracle-design problem is therefore not "the team picked a thin venue when a deeper venue was available"; it is "the chain's DEX-liquidity profile in 2021 made a single-source oracle the path of least resistance, and there was no audit-firm checklist or framework default that would have pushed the team toward a multi-venue design under those constraints." The 3% refresh threshold made the surface particularly clean to exploit — it produced a known target deviation rather than requiring the attacker to estimate how much movement would propagate.
- Pre-event (industry-context layer, cross-chain lesson propagation): the bZx incidents (February 2020) and the Harvest Finance incident (October 2020) had, by September 2021, established the T9.001 + AMM-pool-state-as-oracle pattern as the canonical first-class DeFi attack and produced widely-circulated technical post-mortems. Eighteen months had elapsed between bZx and Vee Finance, and Avalanche's DeFi ecosystem had launched and reached billions in TVL during that window. The defender-portfolio observation is that cross-chain lesson propagation was systematically slower than within-chain propagation: Ethereum protocols that deployed in 2021 broadly used TWAP-windowed or multi-source oracles after Harvest, while protocols launching on newer chains (Avalanche, BSC, Solana, then-emerging L1s) inherited the bZx-era surface because the audit firms working those chains, the framework templates available, and the deployer-tool defaults had not propagated the post-Harvest oracle-resilience standard. Vee Finance is the cleanest instance of this pattern in the Avalanche ecosystem and one of the cleanest cross-chain examples in the OAK record.
- Pre-event (trust-boundary layer): the cToken-wrapper validation gap is mechanically distinct from the oracle-source gap and would have produced an exploitable surface even with a perfect oracle, because the slippage check resolved the underlying token through an attacker-supplied wrapper. BlockSec's framing — that the price oracle was not the proximate failure — is technically defensible. The two layers compose, and OAK's classification follows the outcome shape (manipulated-price extraction in a leveraged-trading protocol), which places Vee Finance in T9.001 even when the proximate-cause description leads with a wrapper-validation issue.
- At-event (oracle-side signal): within the exploit cycles, Pangolin pool prices for the attacker-seeded pairs moved sharply on attacker swaps. A multi-venue deviation monitor — comparing Pangolin pool-derived prices against any external reference (Chainlink stablecoin feeds where available, CEX mid-prices for major assets, or simply a TWAP-windowed alternative) — would have observed the divergence in the same block as the manipulation. For long-tail Avalanche assets where no external reference existed in September 2021, the available defender control is a TWAP window on the Pangolin price itself; even a 30-minute TWAP would have substantially raised the cost of the attack.
- At-event (protocol-side signal): the same actor was both the marginal liquidity-provider on the manipulated Pangolin pairs and the marginal leveraged-trade originator against those pairs on Vee Finance, in the same window, with funds traceable directly to a Tornado Cash withdrawal eight minutes before the first exploit transaction. A cross-action correlation detector — same actor, supply-liquidity-then-trade-against-it on the consuming protocol, recent-Tornado-Cash-funding flag — would have produced an independent signal. Vee Finance had no such monitor, and the broader Avalanche-monitoring vendor coverage in September 2021 was thin.
- Post-event (recovery channel): the attacker did not respond to the bounty offer and laundered proceeds through standard cross-chain channels (0x, Curve.fi, Ren BTC). Recovery was zero from the attacker. The realised user-side recovery came from the protocol absorbing the loss into a revenue-funded compensation pool — a third recovery-channel category alongside on-chain-only laundering (Cream October 2021), unprompted partial return (Harvest October 2020), and explicit-negotiated-recovery (Mango Markets October 2022). Protocol-funded reimbursement is observed elsewhere in the corpus (e.g., bZx's own compensation flow) but is rare and depends on the protocol having ongoing revenue and surviving the reputational hit.
What this example tells contributors writing future Technique pages
- Cross-chain lesson-propagation gaps are a structural T9.001 observation. The canonical T9.001 chain — bZx (Feb 2020) → Harvest (Oct 2020) → Vee Finance (Sep 2021) → Cream (Oct 2021) → Mango Markets (Oct 2022) — straddles three chains (Ethereum, Avalanche, Solana) and four oracle-architecture sub-patterns. Vee Finance occupies the slot between Harvest and Cream chronologically and is the first non-Ethereum entry in the canonical chain. Worked examples of T9.001 cases on chains other than Ethereum should explicitly note the cross-chain propagation gap: protocols launched on chains that themselves emerged in 2020-2021 inherited bZx-era oracle vulnerabilities at industry-wide scale, because the Ethereum-specific defender knowledge (TWAP windows, multi-source quorum, deviation breakers) had not propagated into the audit-firm checklists, framework templates, and deployer defaults of those new ecosystems. T9.001 pages should describe this structural gap, not just the per-incident technical details.
- Single-source oracle is a function of chain-level DEX-liquidity profile, not always a team choice. Worked examples should resist treating "the team picked a thin oracle source" as the defender-relevant frame on chains where the chain's own liquidity profile makes a single-source oracle the only feasible path. Vee Finance's Pangolin dependency was, in September 2021, the same kind of constraint that early-Ethereum protocols had with Kyber and Uniswap V1 in 2019-2020. The defender-relevant question is whether the protocol had any fallback (TWAP window, deviation breaker, kill-switch on extreme moves), not whether it picked the deepest available venue.
- Threshold-style refresh triggers are a distinct sub-failure within T9.001. Harvest's 3% per-cycle threshold capped per-action profit but allowed multi-cycle repetition; Vee Finance's 3% refresh threshold did the opposite — it gave attackers a clean target deviation to aim at, and allowed a single sufficiently-large move to redefine the canonical price. T9.001 pages should distinguish these two threshold-style failures since they invite different mitigation guidance: Harvest needs cumulative-deviation circuit breakers, Vee Finance needs TWAP windows that smooth out the threshold trigger.
- The trust-boundary-mismatch in the cToken wrapper is mechanically distinct from the oracle source but composes with it. BlockSec's "the oracle was not compromised" framing is correct in its narrow sense and wrong as a Technique-level classification — OAK classifies by outcome shape (manipulated-price extraction in a leveraged-trading protocol), not by which proximate component is described first. Worked examples should preserve dissenting forensic analyses where they exist, since the dissent often surfaces a sub-pattern (here, wrapper-resolution-mismatch as a slippage-check bypass) that may belong as its own Technique page in a later OAK version.
- Protocol-funded reimbursement is a real recovery channel and should be tracked separately. Vee Finance's response — the protocol absorbing the loss and funding a compensation pool from ongoing revenue — is a distinct outcome shape from on-chain laundering (no recovery), unprompted partial return (Harvest), and negotiated recovery (Mango). It depends on the protocol surviving the reputational hit and continuing to generate revenue, which is a strong filter; most exploited protocols do not. Worked examples should note this category since it materially changes the realised user-side loss base rate for cases that fit the filter.
Public references
- Vee Finance — The Main Cause of Vee Finance Attack — the protocol-side official post-mortem; canonical source for the single-source-oracle and decimals-unaware-slippage-check framing —
[veefinancepostmortem2021]. - Vee Finance — Latest Update & Compensation Plan (Sept 25) — first published version of the compensation plan; cited for the protocol-funded reimbursement framing —
[veefinancecompensation2021]. - Vee Finance — Vee.Finance Restart Plan (September 28) — cited for the suspended-contract status and the platform-restart sequence.
- Vee Finance — The compensation pool will be open on October 31 — cited for the final compensation-pool composition (AVAX, WBTC, WETH, LINK, USDT) and the revenue-funded payout cadence.
- SlowMist — The Main Cause of Vee Finance Attack — independent forensic write-up; cited for the oracle-side framing and the decimal-mismatch slippage-check bypass —
[slowmistveefinance2021]. - Halborn — Explained: The Vee Finance Hack (September 2021) — protocol-side function-level walkthrough —
[halbornveefinance2021]. - BlockSec — The Real Root Cause of the Vee Finance Security Incident — dissenting forensic analysis foregrounding the cToken-wrapper validation gap —
[blocksecveefinance2021]. - ImmuneBytes — Vee Finance Exploit — Sep 21, 2021 — Detailed Analysis — independent transaction-level walkthrough —
[immunebytesveefinance2021]. - rekt.news — Vee Finance — REKT — contemporaneous narrative write-up; cited for the Tornado Cash funding pattern and the asset-flow figures (8,804 WETH, 214 WBTC) —
[rektveefinance2021]. - TRM Labs — Vee and Zabu Finance Exploits: Two Uncannily Similar Attacks — comparative laundering-pattern analysis; cited for the attacker-address (
0xeeeE…95ba), the 0x / Tornado Cash funding, and the Avalanche-cohort framing —[trmveefinance2021]. - CoinDesk — Vee Finance Hit for $35M in Second Major Exploit on Avalanche — contemporaneous reporting; cited for the Avalanche-second-major-exploit framing —
[coindeskveefinance2021]. [zhou2023sok]— academic taxonomy classifying Vee Finance as a price-oracle-manipulation case in the broader DeFi-incident corpus.[bzxpostmortem2020]— companion T9.001 origin citation; cited here for the eighteen-months-since-precedent observation, not for Vee Finance specifics.
Discussion
Vee Finance September 2021 is the third link in the canonical T9.001 chain — bZx (Feb 2020) → Harvest (Oct 2020) → Vee Finance (Sep 2021) → Cream (Oct 2021) → Mango Markets (Oct 2022) — and the first non-Ethereum entry in that chain. The slot is structurally important: Vee Finance precedes Cream by about five weeks chronologically and occurred on a different chain, which means the same Technique class produced two large-scale extractions in the same calendar quarter against protocols that did not share auditors, frameworks, or deployer tooling. Read together, Harvest, Vee Finance, and Cream demonstrate that the T9.001 lessons from bZx (Feb 2020) had not consistently absorbed across the industry by the end of 2021 — the canonical post-mortems were public and widely read, but the propagation channel was informal (write-ups and Twitter) rather than structural (audit-firm checklists, framework defaults, deployer-tool guards), and the absorption rate was correspondingly uneven. Vee Finance's specific contribution to the chain is the cross-chain dimension of that propagation gap: chains that launched and grew their DeFi ecosystems during the 2020-2021 window inherited the bZx-era oracle-design surface at industry-wide scale, because the Ethereum-specific defender knowledge had not been ported into the new ecosystems' audit-and-deploy tooling. The dollar magnitudes (~$1M → ~$24M → ~$35M → ~$130M → ~$110M) are not monotonically increasing across the chain, but the per-chain coverage is: Ethereum (bZx, Harvest, Cream), Avalanche (Vee Finance), Solana (Mango Markets) — which is the right read for contributors documenting future T9.001 cases on chains that are not yet represented in the canonical chain. The Vee Finance compensation-pool resolution is also a v0.1 reference for the protocol-funded-reimbursement recovery channel, distinct from the on-chain-laundering, partial-return, and negotiated-recovery shapes in the other links, and useful for risk-modelling base rates that condition on the protocol surviving the post-incident period.