Fortress Protocol FTS Collateral-Listing Governance Capture / Public submit() Oracle Manipulation Drain (2022-05-08)

  • Name: Fortress Protocol FTS collateral-listing governance capture / public submit() oracle manipulation drain
  • Date: 2022-05-08
  • Protocol: Fortress Loans / Fortress Protocol (JetFuel Finance lending arm)
  • Chain: BNB Chain
  • Category: governance capture / oracle manipulation / protocol-native collateral fragility / lending-market drain
  • Loss: about 1,048.1 ETH plus 400,000 DAI, or roughly $2.98M to $3M
  • Summary: Fortress did not fall to one isolated oracle bug. The attacker first pushed governance proposal 11 through FortressGovernorAlpha to make the thinly traded house token FTS accepted collateral at a 0.7 collateral factor, then abused the oracle path behind FortressPriceOracle because the upstream Chain.submit() authentication checks had effectively been disabled. Once Fortress was willing to treat protocol-native FTS as borrowable collateral and also willing to believe an attacker-submitted price for that same token, roughly 100 FTS could be marked at fantasy value and used to borrow out the rest of the market.
  • Trigger / entry point:
    • Fortress governance was cheap enough that contemporary reporting and CertiK both describe the attacker acquiring just over 400,000 FTS and using it to create and carry malicious proposal 11.
    • Proposal 11 changed Fortress risk parameters so FTS itself became acceptable collateral with collateral factor 700000000000000000 (70%).
    • The oracle path FortressPriceOracle -> Chain.submit() accepted attacker-shaped price submissions because the relevant signature / power validation in Chain.submit() had been commented out or disabled in deployment.
    • Fortress then let the same thin governance token sit in the solvency core of the lending market at an attacker-chosen price.
  • Root cause:
    • Fortress governance could directly change live lending collateral parameters even though the effective cost to control that vote was tiny relative to protocol TVL.
    • Fortress admitted its own low-depth governance token FTS as collateral, turning a thin local market into solvency truth for stronger reserve assets.
    • The oracle implementation delegated trust to a Chain contract whose submit() path no longer enforced the authentication assumptions the rest of the protocol relied on.
    • There was no operational backstop strong enough to stop an obviously dangerous governance proposal even though REKT reported it sat active for about three days.
  • Exploit path:
    1. The attacker funded BNB Chain activity from Ethereum-side funds that reporting traced back to Tornado Cash, then staged BNB Chain address 0xA6AF2872176320015f8ddB2ba013B38Cb35d22Ad and attack contract 0xcd337b920678cf35143322ab31ab8977c3463a45.
    2. The attacker accumulated enough FTS to control the sleepy governance surface and used helper wallet 0x0dB3B68c482b04c49cD64728AD5D6d9a7B8E43e6 to submit malicious proposal 11 through FortressGovernorAlpha 0xe79ecdb7fedd413e697f083982bac29e93d86b2e.
    3. Proposal 11 passed and was executed, changing Fortress so FTS could be posted as collateral with a 70% collateral factor.
    4. The attacker then abused Chain contract 0xc11b687cd6061a6516e23769e4657b6efa25d78e, whose submit() function no longer enforced the expected signer / power checks, and fed a malicious FTS price into FortressPriceOracle 0x00fcF33BFa9e3fF791b2b819Ab2446861a318285.
    5. With FTS both governance-approved and oracle-inflated, the attacker posted about 100 FTS through attack contract 0xcd337... as collateral and borrowed large quantities of stronger assets across Fortress’s lending markets in exploit transaction 0x13d19809b19ac512da6d110764caee75e2157ea62cb70937c8d9471afcb061bf.
    6. The borrowed assets were swapped into ETH and DAI, then moved off BNB Chain via Celer / Multichain routes and ultimately sent into Tornado Cash.
  • What the attacker needed to be true:
    • FTS governance participation had to be so weak that buying a few hundred thousand tokens on market was enough to carry a malicious proposal.
    • Governance had to retain direct authority over collateral listing / collateral-factor changes for the live lending system.
    • FTS had to remain thin enough that its local quoted price could not support the borrowing power the protocol was prepared to assign to it.
    • FortressPriceOracle had to trust Chain.submit() results without an independent sanity layer that would reject unauthenticated or absurd FTS prices.
    • The market had to hold deeper-liquidity borrow assets than the true executable value of the posted FTS collateral.
  • Technical anatomy worth remembering:
    • This is a clean composed failure where governance capture was not the final payout rail by itself. Governance first rewired risk parameters, and the oracle bug then monetized that new risk surface.
    • The dangerous asset was Fortress’s own governance token. That makes this more specific than generic oracle manipulation: the protocol let a house asset become balance-sheet truth.
    • The oracle weakness was not subtle market microstructure. CertiK’s writeup says the critical validation inside Chain.submit() had effectively been removed, so the protocol’s trusted price source had collapsed into a public write surface.
    • The incident is also a useful governance-monitoring lesson. REKT noted the malicious proposal sat active for roughly three days, so Fortress’s constitutional defense failed well before the exploit transaction.
  • Representative transactions and addresses:
    • Exploit transaction: 0x13d19809b19ac512da6d110764caee75e2157ea62cb70937c8d9471afcb061bf
    • Proposal-creation transaction for proposal 11: 0x12bea43496f35e7d92fb91bf2807b1c95fcc6fedb062d66678c0b5cfe07cc002
    • Vote transaction highlighted by CertiK: 0x83a4f8f52b8f9e6ff1dd76546a772475824d9aa5b953808dbc34d1f39250f29d
    • Attacker EOA: 0xA6AF2872176320015f8ddB2ba013B38Cb35d22Ad
    • Helper / proposal wallet: 0x0dB3B68c482b04c49cD64728AD5D6d9a7B8E43e6
    • Attack contract: 0xcd337b920678cf35143322ab31ab8977c3463a45
    • FortressGovernorAlpha: 0xe79ecdb7fedd413e697f083982bac29e93d86b2e
    • FortressPriceOracle: 0x00fcF33BFa9e3fF791b2b819Ab2446861a318285
    • Upstream Chain contract: 0xc11b687cd6061a6516e23769e4657b6efa25d78e
  • Response / mitigation:
    • Fortress / JetFuel publicly acknowledged the incident, paused the UI, and pointed users to a follow-up governance proposal intended to repair the damage.
    • The immediate lesson was broader than patch the oracle: Fortress had to treat governance control over collateral admission and the oracle-authentication path as the same security surface.
    • Even after the exploit, the case remained an uncomfortable reminder that a lending market should not wait for social monitoring to catch obviously malicious risk-parameter proposals.

Pattern tags

Why the exploit worked

  • Fortress let a weakly defended governance surface write directly into live lending risk. Proposal 11 was not cosmetic policy; it changed what the protocol would accept as collateral and therefore what counted as solvency truth.
  • The newly admitted collateral was Fortress’s own thinly traded governance token. That meant the attacker did not need to buy or sustain real market depth large enough to justify the borrow power they were about to extract; they only needed the protocol to treat FTS as money-good collateral in the first place.
  • The oracle path then removed the last remaining restraint. Once FortressPriceOracle trusted a Chain.submit() surface whose signature / voting-power checks were effectively disabled, the attacker did not have to manipulate an honest market — they could simply publish the fantasy price the lending engine would trust.
  • These were not two separate bugs with independent blast radii. Cheap governance first created the dangerous collateral lane, and the broken oracle then monetized that exact lane. The exploit worked because collateral admission, house-token market quality, and oracle authentication were all part of one joined borrow-authority object.
  • Fortress also lacked a real constitutional backstop. A proposal that turned a low-float governance token into 70%-factor collateral reportedly sat live for days, which means the protocol’s practical defense model had already failed before the final borrow transaction.

Detection and audit pivots

  • Treat governance-controlled collateral listings and collateral-factor changes as treasury-grade actions. Ask what token float, borrowable voting power, quorum profile, and emergency-veto latency would be required for a malicious listing to pass right now.
  • For every protocol-native or low-depth asset that governance could admit as collateral, ask whether the protocol is about to let its own local token narrative become solvency truth for deeper reserve assets. Thin house tokens deserve extra skepticism even before any oracle review begins.
  • Trace the exact oracle-authentication path all the way down to the write surface. If the protocol believes a submit() call is backed by signatures, voting power, reporters, or validator weights, verify where that check actually happens onchain and whether deployment drift commented it out or bypassed it.
  • Review composition, not components in isolation. A governance system that can list collateral and an oracle that can publish its price may each look survivable alone, but together they can create an instant list thin thing, price thin thing, borrow everything else path.
  • Monitor queued and active governance proposals for parameter combinations, not only for admin-target changes. New collateral + high collateral factor + weak market depth + same-token oracle dependency should already look like an emergency condition.
  • Ask what bounded-loss controls survive if governance or pricing truth fails anyway: listing caps, borrow caps, per-asset debt ceilings, collateral quarantine windows, or delays before newly admitted collateral can support large borrowing.

Failure-prevention checklist

  • Do not let low-float governance tokens become normal lending collateral just because governance can vote it through. Protocol-native assets need stricter admission rules, lower or zero borrow power by default, and explicit market-depth / unwind tests before they ever reach solvency-critical status.
  • Treat collateral listing, collateral-factor changes, and oracle-source changes as treasury-grade actions with stronger quorum, longer delay, narrower proposer sets, or an emergency veto. If one sleepy vote can rewrite borrow truth, governance is already acting like an admin key.
  • Keep newly listed or newly reconfigured collateral in borrow-side quarantine. A passed proposal should not immediately let the same asset support deep borrowing before caps, canaries, and independent review confirm the market and oracle assumptions are real.
  • Require hard oracle authentication at the final write surface. If FortressPriceOracle trusts Chain.submit(), then submit() must itself prove reporter identity, voting power, signature set, and freshness rather than hoping an upstream assumption survived deployment.
  • Bound losses even if governance or price publication fails: per-asset debt ceilings, borrow caps, collateral caps, isolated listings, and fast pause paths should stop one bad listing from draining the whole market.
  • Monitor governance for economic nonsense, not only code-change proposals. Thin house token + high collateral factor + same-token oracle dependency should already page humans before execution.
  • Make proposal-review and emergency-response ownership explicit. A three-day malicious proposal window means the protocol lacked a credible constitutional backstop even before the exploit transaction.

Audit prompts

  • Exactly which governance actions can change live borrow authority here: listing a market, changing collateral factor, swapping oracle sources, or editing reporter / submitter sets?
  • How expensive is malicious control in practice, not in theory? What float is liquid, what fraction is borrowable, how concentrated is turnout, and how quickly could an attacker buy or rent quorum?
  • If the protocol listed its own token as collateral tomorrow, what independent market-depth, liquidity, and exit assumptions would justify that decision? Are any of those assumptions actually enforced onchain?
  • Where does oracle authentication really happen? Trace the path through every adapter and helper until you reach the final state write, then verify that signature, power, reporter-set, and freshness checks still exist in deployed code.
  • If governance successfully lists dangerous collateral, what stops immediate full-size borrowing before humans react: caps, quarantine delays, isolated markets, utilization throttles, or nothing?
  • Does the same organizational surface control both collateral admission and collateral pricing? If so, the review target is not governance plus oracle; it is one combined borrow-authority object.
  • What alerts fire for active proposals that would make protocol-native or low-depth assets systemically important, and who is actually empowered to block them?
  • If the oracle path becomes publicly writable or governance gets captured, what is the maximum extractable value before pauses, caps, or market isolation take effect?

Lessons that should already be standard

  • Governance is already a hot wallet when it can list collateral or rewrite collateral factors for a lending market. Calling it a DAO does not reduce the need for treasury-grade controls.
  • Protocol-native tokens are not neutral collateral candidates. If the protocol is the main source of narrative, liquidity, and incentive demand for an asset, the bar for making that asset borrow-power truth should be extremely high.
  • An oracle is only as strong as its last authenticated write surface. If the final submit() lane is public, then every elegant upstream trust story is already dead.
  • Cheap governance and weak oracle auth are multiplicative, not additive, risk. One creates a dangerous lane; the other makes that lane immediately cash-outable.
  • Watching proposals in Discord or Telegram is not a security model. If a malicious listing can sit live for days and still execute, the constitutional defense is already broken.
  • Deep-liquidity reserves should never fully trust a newly admitted, low-depth, or protocol-native collateral asset without tight caps and time to prove that its price path is adversarially robust.

Why this incident matters

  • It is a strong preserved example of how two medium-strength failures can compose into a total drain: cheap governance plus a public oracle write surface.
  • It sharpens the protocol-native collateral fragility pattern because the attacker did not need deep external market support for FTS; they only needed Fortress to believe Fortress’s own token was money-good collateral.
  • It also broadens governance-capture notes beyond treasury sweeps and admin seizures. Here, governance capture mattered because it changed what the lending engine was willing to believe about collateral.

Internal linkages

Control surface