Belt beltBNB Share Inflation
Exploit Transactions
0x13e75878a21af9a9b2207f5d9e18f19a43083a9ffbac36df5a7d4d67a52c164fVictim Addresses
0xa8bb71facdd46445644c277f9499dd22f6f0a30cBSC0x33adbf5f1ec364a4ea3a5ca8f310b597b8afdee3BSC0xd4bbc80b9b102b77b21a06cb77e954049605e6c1BSC0xda937ddd1f2bd57f507f5764a4f9550c750f7b31BSCLoss Breakdown
Similar Incidents
Channels Dust-Share Drain
35%BankrollNetworkStack self-buy dividend inflation exploit
33%Helio Plugin Donation Inflation
33%Palm PLP AUM Inflation
33%Flashstake LP Share Inflation
31%LibertiVault Reentrant Share Inflation
31%Root Cause Analysis
Belt beltBNB Share Inflation
1. Incident Overview TL;DR
On BNB Chain transaction 0x13e75878a21af9a9b2207f5d9e18f19a43083a9ffbac36df5a7d4d67a52c164f at block 33112359, the attacker EOA 0xfe2105e1317dfd6ed3887bf7882977c03cfebb7c used a DODO flash loan and Venus leverage to build a temporary beltBNB position, route it through NativeFarm pid 135, and withdraw more beltBNB than was deposited. The surplus beltBNB was immediately redeemed back into WBNB, public debts were repaid, and 0.549178782964712364 WBNB was transferred from the helper contract back to the attacker EOA.
The root cause is a stale-accounting share mint in Belt Finance's beltBNB farm stack. StrategyBelt_Token.deposit mints shares using the pre-_farm() wantLockedTotal, but _farm() then deposits the attacker's beltBNB into MasterBelt and realizes previously pending BELT rewards in the same state transition. NativeFarm and MasterBelt later redeem those inflated shares against the updated asset base, so the attacker exits with 3.190290669631425046554 beltBNB after depositing only 3.189806224269560876070.
2. Key Background
beltBNB at 0xa8bb71facdd46445644c277f9499dd22f6f0a30c is a Belt vault token redeemable into WBNB through the public Belt vault path. The exploit does not depend on private privileges: every external call in the incident goes through public entrypoints on DODO, Venus, beltBNB, NativeFarm, StrategyBelt_Token, and MasterBelt.
NativeFarm at 0x33adbf5f1ec364a4ea3a5ca8f310b597b8afdee3 and MasterBelt at 0xd4bbc80b9b102b77b21a06cb77e954049605e6c1 are wrapper farms that track user ownership in shares and convert back to assets on withdrawal using user.shares * wantLockedTotal / sharesTotal. That structure is safe only if the strategy's share minting uses the full economic value of the strategy at deposit time.
StrategyBelt_Token at 0xda937ddd1f2bd57f507f5764a4f9550c750f7b31 compounds BELT rewards through MasterBelt. Pending BELT is public, claimable, and can be forced into the strategy state through ordinary deposit and earn flows, so any stale denominator at share-mint time can be turned into a real over-withdrawal.
3. Vulnerability Analysis & Root Cause Summary
The vulnerability is an accounting bug in share issuance, not an access-control failure. StrategyBelt_Token.deposit computes sharesAdded before calling _farm(), so the deposit is priced against stale wantLockedTotal. _farm() then pushes the newly received beltBNB into MasterBelt, and MasterBelt.deposit also releases BELT rewards that had already accrued to the strategy's existing position. Those rewards increase the strategy's economic value, but they were excluded from the denominator used to mint the new shares. The attacker therefore receives more strategy shares than the deposited beltBNB should buy. NativeFarm and MasterBelt subsequently treat those shares as ordinary ownership and redeem them against the updated wantLockedTotal, which yields excess beltBNB on exit. Because beltBNB is redeemable to WBNB through public vault code, the accounting error becomes immediately realizable profit in the same transaction.
4. Detailed Root Cause Analysis
The critical strategy code path is the order of operations in StrategyBelt_Token.deposit and _farm():
uint256 sharesAdded = _wantAmt;
if (wantLockedTotal > 0) {
sharesAdded = _wantAmt
.mul(sharesTotal)
.mul(entranceFeeFactor)
.div(wantLockedTotal)
.div(entranceFeeFactorMax);
}
sharesTotal = sharesTotal.add(sharesAdded);
_farm();
IMasterBelt(farmContractAddress).deposit(pid, wantAmt);
wantLockedTotal = wantLockedTotal.add(wantAmt);
This ordering is the breakpoint. The share mint uses stale wantLockedTotal, then _farm() deposits into MasterBelt, where already pending BELT is realized during the same transition. The seed trace confirms the reward realization leg directly:
0xD4BbC80b9B102b77B21A06cb77E954049605E6c1::deposit(9, 3189806224269560876070)
BELT::transfer(0xdA937DDD1F2bd57F507f5764a4F9550c750F7B31, 6400560872148458630032)
The farm wrappers then convert those inflated shares back to assets using the standard Belt withdrawal formula. NativeFarm uses:
uint256 wantLockedTotal = IStrategy(poolInfo[_pid].strat).wantLockedTotal();
uint256 sharesTotal = IStrategy(poolInfo[_pid].strat).sharesTotal();
uint256 amount = user.shares.mul(wantLockedTotal).div(sharesTotal);
MasterBelt uses the same share-to-asset conversion pattern. Once the attacker has obtained underpriced shares from StrategyBelt_Token.deposit, both wrappers overpay deterministically on withdrawal.
The exploit trace matches that mechanism exactly. The attacker first minted 3.189804952156188847410 beltBNB from a 3,600.001 WBNB deposit into Belt, then sent 3.189806224269560876070 beltBNB into NativeFarm pid 135. The nested strategy call sequence is:
0x33AdBf5f1ec364a4ea3a5CA8f310B597B8aFDee3::deposit(135, 3189806224269560876070)
0xdA937DDD1F2bd57F507f5764a4F9550c750F7B31::deposit(..., 3189806224269560876070)
0xD4BbC80b9B102b77B21A06cb77E954049605E6c1::deposit(9, 3189806224269560876070)
0xdA937DDD1F2bd57F507f5764a4F9550c750F7B31::earn()
0xD4BbC80b9B102b77B21A06cb77E954049605E6c1::withdraw(9, 0)
0x33AdBf5f1ec364a4ea3a5CA8f310B597B8aFDee3::withdraw(135, 63796124485391217521400)
After the round trip through the stale-share path, the attacker withdrew 3.190290669631425046554 beltBNB and then redeemed it through beltBNB.withdraw, which returned 3.600549178782964712364 WBNB. The public DODO and Venus debts were fully repaid, and the helper transferred the residual 0.549178782964712364 WBNB back to the attacker EOA.
The updated ACT profit predicate is also deterministic. Using only public block-33112358 prices and balances, the attacker EOA portfolio was worth 0.048354344778383572 WBNB before the exploit and 0.585477065740839199 WBNB after the exploit, for a net increase of 0.537122720962455627 WBNB after gas. The valuation inputs are:
getUnderlyingPrice(vUSDT) = 1000130000000000000getUnderlyingPrice(vBNB) = 224244954640000000000beltBNB.getPricePerFullShare() = 1128595965571179842
Those values are sufficient to reproduce the WBNB-denominated pre-state and post-state attacker portfolio values from public data alone.
5. Adversary Flow Analysis
- In tx
0x44ed5c199bea722278fa37e0246ff1a9a08d1405a205e3c06002ff2b880f8e3d, the attacker minted a smallbeltBNBseed from0.002WBNB. In tx0x8c3c0ca43dda51701d9c44a4a5866a3fe984989ec8030c0d72b398fd1b90094f, the attacker deployed helper contract0x22ad9eef79615a1592e969bdf7b238a07281ab80. - In the exploit tx, the helper flash-borrowed
3,100WBNB and150,000USDT from DODO, posted150,155.049710721328089USDT to Venus, borrowed500BNB, wrapped it, and deposited3,600.001WBNB intobeltBNB. - The helper deposited its entire
beltBNBbalance intoNativeFarmpid135. This invoked the stale-share mint inStrategyBelt_Token.deposit, then forced BELT reward realization throughMasterBelt.depositandStrategyBelt_Token.earn. - The helper withdrew from
NativeFarmusing the now-inflated share balance, received3.190290669631425046554beltBNB, and redeemed it back to WBNB through the publicbeltBNBwithdrawal path. - The helper repaid the Venus BNB debt and both DODO flash-loan legs, then transferred
0.549178782964712364WBNB back to attacker EOA0xfe2105e1317dfd6ed3887bf7882977c03cfebb7c.
6. Impact & Losses
The protocol-side extraction is visible in the farm accounting itself: the attacker obtained 0.485717475236199144 more beltBNB than a direct beltBNB mint should have produced. That surplus redeemed into 0.548178782964712364 excess WBNB before gas.
From the attacker EOA's public portfolio, the net profit after gas is 0.537122720962455627 WBNB. The loss is borne by existing beltBNB farm participants because their already-accrued BELT rewards were effectively sold to the attacker at a stale share price.
7. References
- Seed exploit tx:
0x13e75878a21af9a9b2207f5d9e18f19a43083a9ffbac36df5a7d4d67a52c164f - Related setup txs:
0x44ed5c199bea722278fa37e0246ff1a9a08d1405a205e3c06002ff2b880f8e3d,0x8c3c0ca43dda51701d9c44a4a5866a3fe984989ec8030c0d72b398fd1b90094f - Seed metadata:
/workspace/session/artifacts/collector/seed/56/0x13e75878a21af9a9b2207f5d9e18f19a43083a9ffbac36df5a7d4d67a52c164f/metadata.json - Seed trace:
/workspace/session/artifacts/collector/seed/56/0x13e75878a21af9a9b2207f5d9e18f19a43083a9ffbac36df5a7d4d67a52c164f/trace.cast.log - Seed balance diff:
/workspace/session/artifacts/collector/seed/56/0x13e75878a21af9a9b2207f5d9e18f19a43083a9ffbac36df5a7d4d67a52c164f/balance_diff.json - Strategy source: https://bscscan.com/address/0xda937ddd1f2bd57f507f5764a4f9550c750f7b31#code
- NativeFarm source: https://bscscan.com/address/0x33adbf5f1ec364a4ea3a5ca8f310b597b8afdee3#code
- MasterBelt source: https://bscscan.com/address/0xd4bbc80b9b102b77b21a06cb77e954049605e6c1#code