Calculated from recorded token losses using historical USD prices at the incident time.
0x1d0af3a963682748493f21bf9e955ce3a950bee5817401bf2486db7a0af104b40x91f1d3c7ddb8d5e290e71f893bad45f16e8bd7baBSC0x4fb9657ac5d311dd54b37a75cfb873b127eb21fdBSCOn BSC transaction 0x1d0af3a963682748493f21bf9e955ce3a950bee5817401bf2486db7a0af104b4 at block 35858190, an unprivileged attacker used a public DODO USDT flashloan to manipulate the BurnsDeFi/WBNB PancakeSwap price, invoke the protocol burn-reward path at the inflated spot price, redeem treasury-backed BNB, unwind the temporary price impact, repay the flashloan, and keep 64324.708722666231791969 USDT in profit.
The root cause was that BurnsBuild treated getAmountsOut on the live BurnsDeFi/WBNB pool as a payout oracle, and BurnsDeFi honored that value by transferring native BNB from treasury directly into the burn reward flow. Because the quote was same-block and attacker-controlled, transient AMM price impact was convertible into deterministic treasury extraction.
BurnsDeFi (0x91f1d3c7ddb8d5e290e71f893bad45f16e8bd7ba) is the primary token contract and also holds native BNB in its own balance. BurnsBuild (0x4fb9657ac5d311dd54b37a75cfb873b127eb21fd) is configured as the BurnsDeFi burnsHolder, so it is the only contract allowed to trigger BurnsDeFi's burnToholder treasury payout path. The forked pre-state at block 35858189 already had launch == true, BurnsBuild set as burnsHolder, and more than 300 BNB in the BurnsDeFi treasury, which made the exploit immediately executable from public state.
The burn-reward design spans two contracts. BurnsBuild's function accepts a quantity of BurnsDeFi to burn, asks the Pancake router for the current BurnsDeFi to WBNB conversion rate, and forwards that quoted amount into BurnsDeFi. BurnsDeFi's then transfers the caller's tokens into the burn-holder path and sends the quoted native BNB amount out of its own treasury. Finally, BurnsBuild's lets the caller redeem the accumulated reward accounting into native BNB during the same transaction.
burnToHolderburnToholderreceiveRewardsThe vulnerability class is an attacker-driven treasury drain caused by using a manipulable AMM spot quote as a treasury redemption oracle. BurnsBuild computes deserved by calling Pancake's getAmountsOut(amount, [BurnsDeFi, WBNB]), which is only a snapshot of the current pool reserves. A flashloan-funded attacker can move those reserves immediately before calling burnToHolder, so the quoted WBNB output ceases to represent a manipulation-resistant valuation. BurnsBuild then forwards that inflated value into BurnsDeFi without any TWAP, cooldown, payout cap, or reserve sanity check. BurnsDeFi only checks that treasury balance is sufficient and then transfers the quoted BNB to BurnsBuild, making the treasury itself the settlement source for the manipulated price. Because BurnsBuild's reward redemption path is same-transaction and permissionless, the attacker can realize the payout before the manipulated price mean-reverts. The result is a deterministic drain of protocol-owned BNB funded entirely by public liquidity and public flashloan capital.
The critical pricing step lives in BurnsBuild:
address[] memory path = new address[](2);
path[0] = address(_burnsToken);
path[1] = uniswapRouter.WETH();
uint256 deserved = uniswapRouter.getAmountsOut(amount, path)[path.length - 1];
require(payable(address(_burnsToken)).balance >= deserved, "not enough balance");
_burnsToken.burnToholder(sender, amount, deserved);
In human terms, BurnsBuild prices a burn by asking the router what the current BurnsDeFi to WBNB spot output would be, then treats that quote as the amount of treasury BNB the burner deserves. That assumption is unsafe because the pair reserves are public and mutable within the same block. The attacker first borrowed 250000 USDT from the public DODO pool 0xd5f05644ef5d0a36ca8c8b5177ffbd09ec63f92f, then swapped through Pancake into BurnsDeFi, increasing the WBNB loaded into the BurnsDeFi pair and pushing the BurnsDeFi/WBNB price upward before the burn reward was calculated.
The treasury transfer itself happens in BurnsDeFi:
require(msg.sender == address(burnsHolder), "only burns");
require(launch, "unlaunch");
uint256 _amount = balanceOf(to);
require(_amount >= amount, "not enough");
super._transfer(to, address(burnsHolder), amount);
uint256 _balance = payable(address(this)).balance;
require(_balance >= balance, "Droped out");
payable(address(burnsHolder)).transfer(balance);
This code does not verify that balance is economically sound. It only checks that BurnsBuild is the caller, the user owns enough BurnsDeFi, and the treasury currently holds enough native BNB to fund the transfer. Once those checks pass, the BurnsDeFi treasury sends the requested BNB directly to BurnsBuild. The invariant that should have held was: treasury-backed burn payouts must remain bounded by a manipulation-resistant valuation and must not be computed from an attacker-controlled transient spot price. The concrete code-level breakpoint is BurnsBuild assigning deserved = getAmountsOut(...) and BurnsDeFi immediately settling that amount from treasury.
The supporting evidence is consistent. The seed balance diff shows BurnsDeFi's native balance moving from 334.456317385659142067 BNB to 45.097795719674116962 BNB, a net loss of 289.358521665985025105 BNB. The same artifact shows the attacker EOA 0xc9fbcf3eb24385491f73bbf691b13a6f8be7c339 ending with a net gain of 64324708722666231791969 smallest units of USDT, which is 64324.708722666231791969 USDT. The forge trace reproducing the incident shows the exact sequence: DODO flashloan, Pancake buy into BurnsDeFi, two burnToHolder calls, receiveRewards, conversion of redeemed BNB into WBNB and then USDT, flashloan repayment, and profit transfer.
The adversary cluster contained the transaction sender EOA 0xc9fbcf3eb24385491f73bbf691b13a6f8be7c339 and the helper contract 0xb5eebf73448e22ce6a556f848360057f6aadd4e7, which was the direct call target for the exploit transaction. The EOA initiated the transaction, and the helper contract executed the flashloan callback, swaps, burn calls, redemption, unwind, and repayment.
The flow was:
250000 USDT from the public DODO pool using a flashloan.BurnsBuild.burnToHolder twice with the acquired BurnsDeFi while the manipulated price is still active. BurnsBuild computes the reward from the manipulated AMM quote and forwards the corresponding BNB claim into BurnsDeFi.BurnsBuild.receiveRewards to convert the accounting entry into spendable native BNB in the same transaction.The reproduced execution trace confirms that the exploit was fully permissionless and same-transaction. No owner role changes, governance actions, or special configuration updates were required. The only preconditions were publicly accessible liquidity, an adequately funded treasury, and BurnsBuild remaining configured as the burnsHolder.
The direct protocol loss was native BNB removed from the BurnsDeFi treasury. The measured loss from the balance diff was:
289358521665985025105 wei of BNB, which is 289.358521665985025105 BNB.The attacker's realized profit was denominated in USDT after the unwind and loan repayment. The balance diff recorded a positive net change of 64324708722666231791969 USDT base units for the attacker EOA, or 64324.708722666231791969 USDT. The economic harm was therefore twofold: BurnsDeFi lost treasury-backed native assets, and the attacker extracted those assets into a liquid stablecoin profit within one transaction.
0x1d0af3a963682748493f21bf9e955ce3a950bee5817401bf2486db7a0af104b40x4fb9657ac5d311dd54b37a75cfb873b127eb21fd0x91f1d3c7ddb8d5e290e71f893bad45f16e8bd7ba0xd5f05644ef5d0a36ca8c8b5177ffbd09ec63f92f0x928cd66dfa268c69a37be93bf7759dc8ee676bf8