bZx/Fulcrum WBTC market manipulation drains ETH liquidity
Exploit Transactions
0xb5c8bd9430b6cc87a0e2fe110ece6bf527fa4f170a4bc8cd032f768fc5219838Victim Addresses
0xb0200b0677dd825bb32b93d055ebb9dc3521db9dEthereum0x4d2f5cfba55ae412221182d8475bc85799a5644bEthereumLoss Breakdown
Similar Incidents
bZx/Fulcrum iETH oracle manipulation enables undercollateralized WETH borrowing
46%SilicaPools decimal-manipulation bug drains WBTC flashloan collateral
38%Ploutos Market Oracle Feed Misconfiguration Enabled Undercollateralized WETH Borrow
34%Aave AMM LP Oracle Manipulation Through Delegated Recursive LP Looping
34%WBTC Drain via Insecure Router transferFrom Path
33%OMPxContract bonding-curve loop exploit drains ETH reserves
33%Root Cause Analysis
bZx/Fulcrum WBTC market manipulation drains ETH liquidity
1. Incident Overview TL;DR
On Ethereum mainnet block 9484688, transaction 0xb5c8bd9430b6cc87a0e2fe110ece6bf527fa4f170a4bc8cd032f768fc5219838 executed an atomic exploit path across dYdX/Compound/bZx/Kyber/Uniswap. The adversary used flash liquidity, borrowed 112 WBTC via Compound, then triggered bZx mintWithEther to force a large protocol-driven WETH -> WBTC buy through Kyber into Uniswap V1 liquidity. Immediately after that price impact, the adversary sold the borrowed WBTC into the same Uniswap pool and extracted 6871.412738870224322944 ETH in the unwind leg. The net attacker EOA delta in native ETH was positive (+64.96890957 ETH after gas accounting in root-cause artifacts). The root cause is an execution/oracle design failure: protocol-critical execution depended on same-transaction spot liquidity and tolerated effectively unbounded slippage in the observed route (minConversionRate = 0).
2. Key Background
The incident is centered on bZx/Fulcrum position-token execution and its downstream trade path.
- Position token used in the incident:
0xb0200b0677dd825bb32b93d055ebb9dc3521db9d. - Trade venue where price impact and unwind happened: Uniswap V1 WBTC/ETH pool
0x4d2f5cfba55ae412221182d8475bc85799a5644b. - Collateral/borrow setup used Compound contracts (
Comptroller,cETH,cWBTC) and borrowed11200000000satoshis of WBTC. - The bZx token logic wraps execution with
setSaneRate/clearSaneRate, but the downstream trade path still called into Kyber/Uniswap with permissive parameters, allowing same-tx price displacement.
Core source context (PositionTokenLogicV2):
modifier fixedSaneRate {
address currentOracle_ = IBZx(bZxContract).oracleAddresses(bZxOracle);
IBZxOracle(currentOracle_).setSaneRate(loanTokenAddress, tradeTokenAddress);
_;
IBZxOracle(currentOracle_).clearSaneRate(loanTokenAddress, tradeTokenAddress);
}
...
(bool success, bytes memory data) = oracleAddress.call(
abi.encodeWithSignature(
"tradeUserAsset(address,address,address,address,uint256,uint256,uint256)",
sourceTokenAddress,
destTokenAddress,
receiver,
receiver,
sourceTokenAmount,
MAX_UINT,
0 // minConversionRate
)
);
Snippet origin: PositionTokenLogicV2 source artifact.
3. Vulnerability Analysis & Root Cause Summary
Root cause category: ATTACK.
The vulnerable behavior is an oracle/execution design issue, not a privileged-key event. The protocol’s leverage/margin execution path accepted same-transaction, spot-liquidity-derived pricing in a manipulable venue. The explicit invariant that should have held is: a single unprivileged transaction must not be able to force materially off-market protocol execution and arbitrage that induced price in the same block. The code-level breakpoint is the downstream oracle trade call with minConversionRate = 0 and huge destination limit, which removed an effective execution floor. In this incident, the attacker sequence exploited that exact condition by first forcing bZx to buy WBTC through thin liquidity, then immediately unwinding borrowed WBTC into the now-distorted pool. Because this was done atomically with flash-loan-scale capital, the exploit became deterministic and repeatable on the forked pre-state.
4. Detailed Root Cause Analysis
Step-by-step mechanism validated from code + trace evidence:
- The attacker transaction established atomic capital and debt setup (Compound
enterMarkets+borrow(11200000000)). - The attacker called
mintWithEtheron the bZx position token, which delegated into PositionTokenLogicV2 and entered thefixedSaneRate-wrapped path. - During that path, the downstream Kyber call executed with
minConversionRate = 0and a very large destination cap, while sourcing Uniswap-linked liquidity. - That protocol-driven WETH->WBTC buy shifted Uniswap pool reserves in the direction required for profitable attacker unwind.
- The attacker then sold all borrowed WBTC (
11200000000) into the same pool and received6871412738870224322944wei. - Balance diffs show final attacker profit signal and pool ETH depletion.
Critical trace evidence (bZx leg and permissive trade params):
...::mintWithEther{value: 1300000000000000000000}(attacker, 0)
...::setSaneRate(WETH9, WBTC)
...::tradeWithHint(WETH9, 5637623762376237623786, WBTC, ..., 10000000000000000000000000000, 0, ...)
...::clearSaneRate(WETH9, WBTC)
Snippet origin: incident transaction trace.
Critical trace evidence (unwind leg):
WBTC::balanceOf(attacker) -> 11200000000
UniswapV1::tokenToEthSwapInput(11200000000, 1, 4294967295)
emit EthPurchase(..., 11200000000, 6871412738870224322944)
Snippet origin: incident transaction trace.
Direct impact evidence from native balance diff:
{
"address": "0x148426fdc4c8a51b96b4bed827907b5fa6491ad0",
"delta_wei": "64968909570000000000"
}
{
"address": "0x4d2f5cfba55ae412221182d8475bc85799a5644b",
"delta_wei": "-1233788976493986699158"
}
Snippet origin: incident balance-diff artifact.
5. Adversary Flow Analysis
Adversary strategy summary: single-transaction, multi-stage extraction using flash liquidity, protocol-induced price move, and immediate unwind.
Adversary-related accounts:
- EOA
0x148426fdc4c8a51b96b4bed827907b5fa6491ad0: transaction sender and final profit recipient. - Contract
0x4f4e0f2cb72e718fc0433222768c57e823162152: attacker orchestrator handling protocol interactions and intermediate ETH. - Contract
0x0de0dd63d9fb65450339ef27577d4f39d095eb85: flash-loan callback executor in the same strategy path.
Victim-side components observed in the flow:
- bZx position token
0xb0200b0677dd825bb32b93d055ebb9dc3521db9d(verified source collected). - bZx loan-token margin path
0x77f973fcaf871459aa58cd81881ce453759281bc(not verified in collected source set). - Uniswap V1 WBTC/ETH pool
0x4d2f5cfba55ae412221182d8475bc85799a5644b(not verified in collected source set).
Lifecycle stages in the incident tx:
- Atomic financing and setup: flash-loan-backed capital setup,
enterMarkets,cETH mint,cWBTC borrow. - Protocol-induced price move:
mintWithEtherpath drives large WETH->WBTC route through Kyber/Uniswap. - Unwind and realization: attacker sells
112 WBTCinto the distorted pool and captures ETH surplus.
6. Impact & Losses
Measured impact (from collector artifacts):
- Uniswap WBTC/ETH pool ETH reserve delta:
-1233.788976493986699158 ETH(-1233788976493986699158 wei). - Attacker EOA native balance delta:
+64.96890957 ETHnet in-transaction signal. - Reported total loss overview in root-cause artifact:
1233.788976493986699158 ETH.
Scope and affected parties:
- Economic loss materialized in AMM liquidity state and protocol-induced toxic execution.
- Incident realized entirely within one public, unprivileged Ethereum transaction.
7. References
- Incident transaction:
0xb5c8bd9430b6cc87a0e2fe110ece6bf527fa4f170a4bc8cd032f768fc5219838(Ethereum mainnet block9484688). - Seed metadata artifact:
/workspace/session/artifacts/collector/seed/1/0xb5c8bd9430b6cc87a0e2fe110ece6bf527fa4f170a4bc8cd032f768fc5219838/metadata.json. - Seed trace artifact:
/workspace/session/artifacts/collector/seed/1/0xb5c8bd9430b6cc87a0e2fe110ece6bf527fa4f170a4bc8cd032f768fc5219838/trace.cast.log. - Seed balance-diff artifact:
/workspace/session/artifacts/collector/seed/1/0xb5c8bd9430b6cc87a0e2fe110ece6bf527fa4f170a4bc8cd032f768fc5219838/balance_diff.json. - Victim-side source artifact:
/workspace/session/artifacts/collector/seed/1/0x579ad3c8abc3658341044c1c6d6dc48f9e015026/src/Contract.sol.