This is a lower bound: only assets with reliable historical USD prices are counted, so the actual loss may be higher.
0x67340bd16ee5649a37015138b3393eb5ad17c195BSC0xc11b687cd6061a6516e23769e4657b6efa25d78eBSCFortress was drained on BNB Chain after an unprivileged adversary combined two public capabilities: execution of already-queued governance proposal 11 and submission of forged Umbrella oracle data. In transaction 0x13d19809b19ac512da6d110764caee75e2157ea62cb70937c8d9471afcb061bf, the attacker executed proposal 11, raised the fFTS collateral factor to 0.7e18, wrote an attacker-chosen FTS-USD price of 40000000000000000000000000000000000, minted 499999999999 fFTS from only 100 FTS, and then borrowed live Fortress liquidity across many markets.
The root cause is an ATTACK-class oracle-authentication failure. Umbrella Chain accepted arbitrary zero-stake signatures in submit(...) and persisted forged first-class data before any effective signer-power validation. Fortress then trusted that forged Umbrella price when valuing fFTS collateral, so borrowAllowed granted borrow power backed by fabricated collateral value.
Fortress exposed FTS as a collateral asset through its fFTS market at 0x854c266b06445794fa543b1d8f6137c35924c9eb, but that collateral became usable only once governance proposal changed the market collateral factor from to . The attacker had already proposed, voted, and queued that change through earlier transactions, so by block the proposal was publicly executable by anyone.
0x6a04f47f839d6db81ba06b17b5abbc8b250b4c62e81f4a64aa6b04c0568dc5010x13d19809b19ac512da6d110764caee75e2157ea62cb70937c8d9471afcb061bf0x851a65865ec89e64f0000ab973a92c3313ea09e80eb4b4660195a14d254cd42511070000000000000000017634589Fortress priced FTS through Umbrella instead of a bounded on-chain market oracle. The exploit trace shows FortressPriceOracle resolving the Umbrella Chain registry entry and reading key FTS-USD immediately before and after the forged submission. Before the exploit write, the trace shows a normal-sized value:
FortressPriceOracle::getUnderlyingPrice(fFTS)
Chain::getCurrentValue(FTS-USD) -> 44812050000000000
The same trace later shows the manipulated value:
FortressPriceOracle::getUnderlyingPrice(fFTS)
Chain::getCurrentValue(FTS-USD) -> 40000000000000000000000000000000000
This matters because Fortress uses that oracle output directly in collateral accounting. Once fFTS received a nonzero collateral factor, a forged FTS price translated directly into artificial borrow capacity.
The exploit is the composition of a public governance state transition and a broken oracle authentication path. Proposal 11 made the fFTS market borrowable collateral by setting markets(fFTS).collateralFactorMantissa = 700000000000000000. That governance action alone was dangerous but not sufficient. The decisive failure was that Umbrella Chain accepted an attacker-crafted oracle submission signed by four recovered addresses that had zero stake, yet still updated the stored first-class data and emitted LogMint with power: 0.
The exploit trace is deterministic on this point. The attacker calls Chain::submit(...), the trace shows four ecrecover operations returning fresh addresses, and the chain token balanceOf checks for those addresses each return 0. Despite that, the call succeeds and emits:
emit LogMint(minter: 0xcD337b920678cF35143322Ab31ab8977C3463a45, blockId: 409819, staked: 8015000000000000000000, power: 0)
That is the invariant break: oracle data that should require authenticated validator power was accepted with zero effective voting power. Fortress then consumed the forged oracle value exactly as designed, so the downstream borrow drains are a consequence of trusting corrupted price data rather than a separate bug in the borrow markets.
The exploit sequence starts from a publicly reachable pre-state. Proposal 11 was already queued; Umbrella Chain, FortressPriceOracle, and the fFTS market were live; and the adversary only needed a fresh helper plus modest FTS and MAHA inventory. The collector artifacts for the proposal queue transaction and the exploit receipt establish those preconditions.
The first critical breakpoint is governance execution. In the verbose exploit trace, the helper calls GovernorAlpha::execute(11), which routes through the timelock into Comptroller::_setCollateralFactor:
Timelock::executeTransaction(Unitroller, 0, "_setCollateralFactor(address,uint256)", ...)
Comptroller::_setCollateralFactor(fFTS, 700000000000000000)
emit NewCollateralFactor(... oldCollateralFactorMantissa: 0, newCollateralFactorMantissa: 700000000000000000)
emit ProposalExecuted(id: 11)
The second critical breakpoint is the Umbrella oracle write. The exploit trace shows the helper calling Chain::submit(...) with forged FTS-USD and MAHA-USD values of 4e34. Before that write, the recovered signer addresses are checked against the staking token and all four balances are zero. Even so, the transaction succeeds and updates the stored data. The subsequent Fortress oracle read immediately returns the forged FTS-USD value. This proves that the write path was not effectively gated by validator stake.
The third breakpoint is collateral manufacture. After the forged price is live, the attacker enters the fFTS market and mints 499999999999 fFTS from a deposit of only 100000000000000000000 FTS. The decoded receipt contains the matching MarketEntered and Mint events:
MarketEntered(market: fFTS, account: exploit_helper)
Mint(minter: exploit_helper, mintAmount: 100000000000000000000, mintTokens: 499999999999)
The final breakpoint is liquidity extraction. The trace shows Comptroller::borrowAllowed(...) approving borrow calls across the Fortress markets after the forged fFTS snapshot is consulted. The balance diff for exploit transaction 0x13d19809... shows real liquidity leaving protocol markets and arriving at the exploit helper, including USDT, USDC, BUSD, BTCB, ETH, LTC, XRP, ADA, DAI, DOT, BETH, SHIB, and val3EPS. For example, fUSDT lost exactly 40989346150386587693923 raw units and fUSDC lost 25362502469320042903093 raw units, while the helper gained the same amounts.
The adversary cluster centered on EOA 0xa6af2872176320015f8ddb2ba013b38cb35d22ad, helper contract 0xcd337b920678cf35143322ab31ab8977c3463a45, and governance-supporting EOA 0x58f96a6d9ecf0a7c3acad2f4581f7c4e42074e70. The earlier governance transactions 0xc368afb2..., 0x83a4f8f5..., and 0x647c6e89... established proposal creation, voting, and queueing for proposal 11.
The active exploit path then unfolded in five adversary-crafted transactions:
0x4800928c95db2fc877f8ba3e5a41e208231dc97812b0174e75e26cca38af5039 deployed the helper.0xd127c438bdac59e448810b812ffc8910bbefc3ebf280817bd2ed1e57705588a0 funded the helper with 100 FTS.0x6a04f47f839d6db81ba06b17b5abbc8b250b4c62e81f4a64aa6b04c0568dc501 funded the helper with MAHA.0x13d19809b19ac512da6d110764caee75e2157ea62cb70937c8d9471afcb061bf executed the full exploit: governance execution, forged oracle submission, fFTS minting, market entry, borrow drain, and metapool monetization.0x851a65865ec89e64f0000ab973a92c3313ea09e80eb4b4660195a14d254cd425 withdrew proceeds from the helper back to the EOA.The exploit transaction itself shows the decision points clearly. First, the helper turns on fFTS collateral through governance execution. Second, it writes a forged oracle value large enough to create overwhelming collateral value. Third, it mints fFTS and enters the market before borrowing. Finally, it drains Fortress cash balances and uses public metapools to convert part of the borrowed inventory into extra USDT. The EOA's USDT balance delta across the exploit and withdrawal sequence is 3055738779429241104386306 raw units.
The incident caused an immediate drain of Fortress borrowable assets once forged fFTS collateral became acceptable. The root_cause artifact attributes the following raw on-chain losses:
[
{"token_symbol":"USDC","amount":"25362502469320042903093","decimal":18},
{"token_symbol":"USDT","amount":"820051999857423582136568","decimal":18},
{"token_symbol":"BUSD","amount":"418909951167111994488637","decimal":18},
{"token_symbol":"BTCB","amount":"22729139539924438159","decimal":18},
{"token_symbol":"ETH","amount":"161205796359835764716","decimal":18},
{"token_symbol":"LTC","amount":"584672766467400973125","decimal":18},
{"token_symbol":"XRP","amount":"36106987338535091504008","decimal":18},
{"token_symbol":"ADA","amount":"51898034974045581151666","decimal":18},
{"token_symbol":"DAI","amount":"51692911822277425590393","decimal":18},
{"token_symbol":"DOT","amount":"3085733193207204598081","decimal":18},
{"token_symbol":"BETH","amount":"3123556747684528478","decimal":18},
{"token_symbol":"SHIB","amount":"990248211251809065999207892","decimal":18},
{"token_symbol":"val3EPS","amount":"629901893448927109680863","decimal":18}
]
The exploit was not limited to a single borrow market. The helper extracted liquidity across the Fortress listing set, then converted part of the borrowed ARTH.usd and MAHA through public pools to realize additional USDT. The recorded EOA-level USDT profit confirms that the attack was economically realized on-chain and not just a transient accounting distortion.
0x13d19809b19ac512da6d110764caee75e2157ea62cb70937c8d9471afcb061bf0x851a65865ec89e64f0000ab973a92c3313ea09e80eb4b4660195a14d254cd4250x647c6e89cd1239381dd49a43ca2f29a9fdeb6401d4e268aff1c18b86a7e932a0/workspace/session/artifacts/collector/iter_4/tx/56/0x13d19809b19ac512da6d110764caee75e2157ea62cb70937c8d9471afcb061bf/receipt.decoded.compact.json/workspace/session/artifacts/collector/iter_4/tx/56/0x13d19809b19ac512da6d110764caee75e2157ea62cb70937c8d9471afcb061bf/balance_diff.json/workspace/session/artifacts/collector/iter_4/tx/56/0x13d19809b19ac512da6d110764caee75e2157ea62cb70937c8d9471afcb061bf/trace.cast.log/workspace/session/artifacts/collector/seed/56/0x06012ded981dd53469c739980608eacf2992ea8f/src/Contract.sol/workspace/session/artifacts/auditor/oracle_definition.json