bZx iYFI Donation Inflation
Exploit Transactions
0x9f8a6ab13a0148d8ad640510692312b9d3d8ac6e0a4165f04ae55dffa18d28a50xf182c20eddb4730c019ddc49cb96fb15aec7a5b1992839efd8046b5b8aba8e1c0xeff478f07c4e1d68f5997510b5a0978afd7f2716dbd65f759180496d955111c40x0fc5c0d41e5506fdb9434fab4815a4ff671afc834e47a533b3bed7182ece73b00xb072f2e88058c147d8ff643694b43a42e36525b7173ce1daf76e6c06170b0e77Victim Addresses
0x7F3Fe9D492A9a60aEBb06d82cBa23c6F32CAd10bEthereum0xD8Ee69652E4e4838f2531732a46d1f7F584F0b7fEthereum0xB983E01458529665007fF7E0CDdeCDB74B967Eb6Ethereum0x2ffa85f655752fB2aCB210287c60b9ef335f5b6EEthereumLoss Breakdown
Similar Incidents
Bao Donation Borrow Exploit
39%bZx/Fulcrum WBTC market manipulation drains ETH liquidity
38%ParaSpace cAPE Donation Repricing
37%Flashstake LP Share Inflation
36%Euler DAI Reserve Donation
35%bZx/Fulcrum iETH oracle manipulation enables undercollateralized WETH borrowing
34%Root Cause Analysis
bZx iYFI Donation Inflation
1. Incident Overview TL;DR
On Ethereum mainnet, the attacker used an empty bZx iYFI market to mint the entire 5-unit iYFI supply with only 5 wei of YFI, then reused those same 5 shares as inflated collateral to borrow assets from bZx loan pools. The inflation came from directly donating flash-borrowed YFI to the iYFI loan-token contract, which changed the share price without minting more iYFI. In the minimal profitable sequence, the attacker progressed from 0.350001808365330129 ETH before nonce 0 to 42.085385398837487612 ETH after transaction 0x0fc5c0d41e5506fdb9434fab4815a4ff671afc834e47a533b3bed7182ece73b0, a net gain of 41.735383590472157483 ETH after setup costs and gas. A later related drain transaction, 0xb072f2e88058c147d8ff643694b43a42e36525b7173ce1daf76e6c06170b0e77, raised cumulative observed profit to 99.021695943580894 ETH.
The root cause is a code-level accounting flaw in bZx LoanTokenLogicStandard: tokenPrice() trusts _totalAssetSupply(), and _totalAssetSupply() trusts the raw YFI balance of the iYFI contract. That means unsolicited YFI transfers into the loan-token contract immediately increase the collateral price of existing iYFI shares even though no new shares were minted.
2. Key Background
iYFI is the bZx loan-token market for YFI collateral. Its share price is derived from the market asset supply divided by the outstanding iYFI supply, so pricing is safe only if the asset-supply term reflects assets that actually back minted shares.
In the collected iYFI implementation, asset supply is computed from the loan-token contract's raw YFI balance plus borrowed assets. Because direct ERC-20 transfers can change that raw balance without going through mint logic, the share price is donation-sensitive.
The exploit depended on an empty market. Before attacker nonce 0, the iYFI market had zero total supply and zero YFI backing. In attacker nonce 2, transaction 0xeff478f07c4e1d68f5997510b5a0978afd7f2716dbd65f759180496d955111c4, the attacker helper swapped public-market WETH for 5 wei YFI and minted exactly 5 iYFI, becoming the sole iYFI holder.
The attacker also deployed its own helper and guard contracts first. Those contracts did not provide privileged access; they were standard attacker-owned infrastructure deployed under normal CREATE semantics, which keeps the opportunity in ACT scope.
3. Vulnerability Analysis & Root Cause Summary
This incident is an ATTACK-class ACT exploit, not an MEV-only unwind and not an access-control issue. The verified victim code shows that iYFI pricing treated unsolicited YFI donations as legitimate collateral backing. Once the attacker owned the entire 5-unit iYFI supply, any YFI donated to the iYFI contract increased the value of those same 5 shares. The attacker used a flash swap to source a large YFI amount, transferred it directly into iYFI, and then borrowed WETH and WBTC against the inflated share price. bZx margin checks accepted the donated value because the borrow path relied on the manipulated iYFI tokenPrice(). After each borrow, the attacker withdrew the same 5 iYFI collateral back out, proving that the protocol treated the same collateral as both fully pledged and immediately withdrawable. The flaw is therefore the donation-sensitive accounting in LoanTokenLogicStandard, with flash liquidity serving only as the funding mechanism.
4. Detailed Root Cause Analysis
The key pricing path in the verified iYFI loan-token implementation is below. This is the decisive code-level breakpoint because _totalAssetSupply() reads the contract's raw YFI balance through _underlyingBalance(), and tokenPrice() feeds that result directly into share valuation:
function tokenPrice() public view returns (uint256) {
uint256 interestUnPaid;
if (lastSettleTime_ != uint88(block.timestamp)) {
(,interestUnPaid) = _getAllInterest();
}
return _tokenPrice(_totalAssetSupply(interestUnPaid));
}
function _underlyingBalance() internal view returns (uint256) {
return IERC20(loanTokenAddress).balanceOf(address(this));
}
function _tokenPrice(uint256 assetSupply) internal view returns (uint256) {
uint256 totalTokenSupply = totalSupply_;
return totalTokenSupply != 0
? assetSupply.mul(WEI_PRECISION).div(totalTokenSupply)
: initialPrice;
}
function _totalAssetSupply(uint256 interestUnPaid) internal view returns (uint256) {
if (totalSupply_ != 0) {
uint256 assetsBalance = _flTotalAssetSupply;
if (assetsBalance == 0) {
assetsBalance = _underlyingBalance().add(totalAssetBorrow());
}
return assetsBalance.add(interestUnPaid);
}
}
The ACT pre-state was Ethereum mainnet immediately before attacker nonce 0 at block 18,695,653. At that point the attacker had not yet deployed the helper or guard, the iYFI market was empty, and no privileged information or privileged addresses were required to proceed.
The bootstrap transaction proves the empty-market setup. The collected balance diff for 0xeff478f07c4e1d68f5997510b5a0978afd7f2716dbd65f759180496d955111c4 shows YFI increasing by 5 wei at iYFI and iYFI increasing by 5 units at the attacker helper. That establishes that the attacker owned 100% of the iYFI supply with only dust backing.
The minimal exploit trace then shows the exact exploit sequence:
LoanTokenLogicStandard::burn(0x03b7..., 5)
LoanTokenLogicStandard::mint(0x03b7..., 5)
YFI::transfer(LoanToken: [0x7F3Fe9D492A9a60aEBb06d82cBa23c6F32CAd10b], 19363816309062560431)
0xB983E01458529665007fF7E0CDdeCDB74B967Eb6::borrow(..., 38089742649328258427, ..., 5, LoanToken: [0x7F3F...], 0x03b7..., 0x03b7..., 0x)
0x91fcdb277e84642Ef29db708Ff35aA48bA20F04d::withdrawCollateral(..., 0x03b7..., 5)
LoanTokenLogicStandard::borrow(..., 22651422, ..., 5, LoanToken: [0x7F3F...], 0x03b7..., 0x03b7..., 0x)
0x91fcdb277e84642Ef29db708Ff35aA48bA20F04d::withdrawCollateral(..., 0x03b7..., 5)
LoanTokenLogicStandard::burn(0x03b7..., 5)
LoanTokenLogicStandard::mint(0x03b7..., 5)
This trace demonstrates all critical state transitions. The attacker first restored the tiny 5-share state, then donated 19.363816309062560431 YFI directly into iYFI, then opened WETH and WBTC borrows using only 5 iYFI as collateral, and then withdrew the same 5 iYFI back out after each borrow. That behavior is impossible unless bZx is valuing the 5 iYFI shares from the donated underlying balance rather than from minted-share accounting.
The attacker EOA and helper balance diffs quantify the realization. The attacker EOA began with 0.350001808365330129 ETH before nonce 0, fell to 0.203289208365230129 ETH after the setup transactions, and ended the minimal exploit transaction with 42.085385398837487612 ETH. The protocol therefore transferred 41.735383590472157483 ETH of net value to an unprivileged adversary in the minimal ACT sequence.
The exploit required only three objective conditions: an otherwise empty iYFI market, the ability to donate YFI directly into the iYFI contract without minting more shares, and continued use of the resulting tokenPrice() in bZx borrow and collateral-withdraw validation. Those conditions are exactly the ACT exploit conditions captured in the validated root cause. The violated security principles are also concrete: collateral pricing must not trust raw ERC-20 balances when unsolicited transfers are possible, share-accounting invariants must distinguish deposits from donations, and collateral withdrawal logic must not rely on a borrower-manipulable collateral price.
5. Adversary Flow Analysis
The attacker cluster consisted of:
0x5a7c7eb8d13a53d42a15d2b1d1b694ccc5141ea5: attacker EOA, sender of nonce 0 through nonce 4 and final profit recipient.0x03b7bb750a974e0bd34795013f66b669f4110e54: attacker helper contract created by that EOA in0xf182c20eddb4730c019ddc49cb96fb15aec7a5b1992839efd8046b5b8aba8e1c.0x65d877b569cc84970baf52c38178c1adf27167c3: attacker guard contract created in0x9f8a6ab13a0148d8ad640510692312b9d3d8ac6e0a4165f04ae55dffa18d28a5and wired into the helper constructor.
The end-to-end attacker flow was:
0x9f8a6ab13a0148d8ad640510692312b9d3d8ac6e0a4165f04ae55dffa18d28a5at block 18,695,654: The attacker deployed the guard contract. This was a normal, permissionless deployment.0xf182c20eddb4730c019ddc49cb96fb15aec7a5b1992839efd8046b5b8aba8e1cat block 18,695,668: The attacker deployed the helper contract and hard-wired public addresses for iYFI, YFI, WETH, routers, pools, and bZx.0xeff478f07c4e1d68f5997510b5a0978afd7f2716dbd65f759180496d955111c4at block 18,695,689: The helper wrapped 100000 wei into WETH, swapped 21 wei WETH for 5 wei YFI, and minted the entire 5-unit iYFI supply.0x0fc5c0d41e5506fdb9434fab4815a4ff671afc834e47a533b3bed7182ece73b0at block 18,695,729: The helper flash-swapped YFI from the public Sushi pair, donated that YFI into iYFI, borrowed 38.089742649328258427 WETH and 0.22651422 WBTC against the inflated price, withdrew the same 5 iYFI collateral back out, repaid the flash swap, and sent the residual profit to the attacker EOA.0xb072f2e88058c147d8ff643694b43a42e36525b7173ce1daf76e6c06170b0e77at block 18,695,746: The attacker repeated the same primitive against additional bZx pools holding AAVE, APE, COMP, DAI, LINK, LRC, MKR, OOKI, UNI, USDC, and USDT.
The helper and guard contracts do not negate ACT status. They were attacker-deployed infrastructure created during the observed sequence, and every required address except those attacker-owned deployments was a public protocol component available to any unprivileged searcher.
6. Impact & Losses
The minimal profitable exploit drained the WETH and WBTC pools immediately:
- WETH:
38089742649328258427raw units, or 38.089742649328258427 WETH. - WBTC:
22651422raw units, or 0.22651422 WBTC.
The repeated transaction then drained at least the following additional assets from other bZx loan pools:
- AAVE:
1203854018221517355 - APE:
115693075453404239155 - COMP:
98157285309061937 - DAI:
39812621697493752003219 - LINK:
523914254804415005610 - LRC:
1987645891232163697748 - MKR:
4481000000000000 - OOKI:
261367663862900000000000 - UNI:
613367858249823222724 - USDC:
42329522649 - USDT:
27251348437
At a protocol level, the impact was broader than the token list. bZx accepted the same 5 iYFI units as collateral multiple times even after the attacker had already withdrawn those units back out, so the protocol's collateralization logic no longer enforced the intended backing invariant.
7. References
- Attacker pre-seed sequence for
0x5a7c7eb8d13a53d42a15d2b1d1b694ccc5141ea5:/workspace/session/artifacts/collector/iter_1/address/1/0x5a7c7eb8d13a53d42a15d2b1d1b694ccc5141ea5/pre_seed_sequence.json - Helper creation provenance for
0x03b7bb750a974e0bd34795013f66b669f4110e54:/workspace/session/artifacts/collector/iter_1/contract/1/0x03b7bb750a974e0bd34795013f66b669f4110e54/creation_provenance.json - Bootstrap trace for
0xeff478f07c4e1d68f5997510b5a0978afd7f2716dbd65f759180496d955111c4:/workspace/session/artifacts/collector/iter_1/tx/1/0xeff478f07c4e1d68f5997510b5a0978afd7f2716dbd65f759180496d955111c4/trace.cast.log - Bootstrap balance diff for
0xeff478f07c4e1d68f5997510b5a0978afd7f2716dbd65f759180496d955111c4:/workspace/session/artifacts/collector/iter_1/tx/1/0xeff478f07c4e1d68f5997510b5a0978afd7f2716dbd65f759180496d955111c4/balance_diff.json - Minimal exploit trace for
0x0fc5c0d41e5506fdb9434fab4815a4ff671afc834e47a533b3bed7182ece73b0:/workspace/session/artifacts/collector/seed/1/0x0fc5c0d41e5506fdb9434fab4815a4ff671afc834e47a533b3bed7182ece73b0/trace.cast.log - Repeated exploit trace for
0xb072f2e88058c147d8ff643694b43a42e36525b7173ce1daf76e6c06170b0e77:/workspace/session/artifacts/collector/seed/1/0xb072f2e88058c147d8ff643694b43a42e36525b7173ce1daf76e6c06170b0e77/trace.cast.log - Verified iYFI loan-token implementation (
LoanTokenLogicStandard):/workspace/session/artifacts/collector/seed/1/0xfb772316a54dcd439964b561fc2c173697aeeb5b/src/Contract.sol