BIGFI Burn Bug Drains PancakeSwap
Exploit Transactions
0x9fe19093a62a7037d04617b3ac4fbf5cb2d75d8cb6057e7e1b3c75cbbd5a5adcVictim Addresses
0xd3d4b46db01c006fb165879f343fc13174a1ceebBSC0xa269556edc45581f355742e46d2d722c5f3f551aBSCLoss Breakdown
Similar Incidents
Sheep Burn Reserve Drain
43%FIREDRAKE Reflection Drain on PancakeSwap
43%OceanLife Reflection Drain on PancakeSwap
42%CS Pair Balance Burn Drain
40%BEVO reflection accounting lets anyone manufacture PancakeSwap input and drain WBNB
38%SafeMoon LP Burn Drain
38%Root Cause Analysis
BIGFI Burn Bug Drains PancakeSwap
1. Incident Overview TL;DR
On BNB Smart Chain block 26685504, transaction 0x9fe19093a62a7037d04617b3ac4fbf5cb2d75d8cb6057e7e1b3c75cbbd5a5adc exploited BIGFI token contract 0xd3d4b46db01c006fb165879f343fc13174a1ceeb and its PancakeSwap pair 0xa269556edc45581f355742e46d2d722c5f3f551a. The adversary cluster consisted of EOA 0x76a88c2baebf251701435abbe8af11ad52b0ab04, which submitted the transaction and paid gas, and exploit contract 0x1a14ccc8f353d16582c0dfab907481b218475959, which executed the strategy.
The exploit borrowed 200000000000000000000000 USDT from public flash-loan pool 0x28ec0b36f0819ecb5005cab836f4ed5a2eca4d13, bought BIGFI, abused BIGFI's public burn(uint256) function to collapse nominal supply from 20999908387035301038246170 to 12800, called sync() on the Pancake pair, and then sold 3 BIGFI back into the manipulated pool for 230466095832979875922923 USDT. After repaying 200160000000000000000000 USDT to the flash-loan pool, the exploit contract retained 30306095832979875922923 USDT. The root cause is a unit-mismatch bug in DxBurnToken::_burn: the function subtracts a token-denominated amount directly from a reflection-denominated balance and reduces _tTotal without the matching _rTotal adjustment.
2. Key Background
BIGFI is a reflection token. For non-excluded accounts, balances are not stored directly in token units. Instead, the token stores reflection balances in _rOwned, and balanceOf(account) returns tokenFromReflection(_rOwned[account]). The conversion rate is derived from _rTotal / _tTotal, so changing total nominal supply without a matching reflection adjustment changes every visible balanceOf result.
That design means the burn path has to preserve unit consistency. Burning x tokens should remove x * currentRate reflections from _rOwned, reduce _tTotal consistently, and keep the supply-side state coherent. BIGFI does not do that. Its public burn(uint256) path accepts any holder call and reaches a private _burn that directly compares a token amount to _rOwned and subtracts that same token amount from _rOwned.
The AMM leg matters because PancakePair 0xa269556edc45581f355742e46d2d722c5f3f551a updates reserves from live token balances when sync() is called. If BIGFI's balanceOf(pair) becomes false because reflection accounting is corrupted, the pair can be re-synced to a fictitious reserve ratio and then immediately drained through a normal swap.
3. Vulnerability Analysis & Root Cause Summary
This incident is an ATTACK-class ACT exploit caused by broken accounting in the victim token, not by a privileged action or off-chain secret. BIGFI's source stores balances in reflection units but exposes them as token units, which is standard for reflection tokens. The bug is that _burn takes a token-denominated input and uses it directly against _rOwned[_addr], even though _rOwned is reflection-denominated. That makes the guard require(_value <= _rOwned[_addr]) far weaker than the intended "caller owns at least _value tokens" condition. Once the attacker buys any meaningful BIGFI balance, their _rOwned value is orders of magnitude larger than their visible token balance, so they can burn an enormous nominal token amount they do not actually hold. Because _tTotal is reduced while _rTotal is not, the reflection rate spikes, balanceOf(pair) collapses, and PancakeSwap prices BIGFI against a false reserve ratio after sync(). The exploit is fully permissionless because all required calls are public: flashLoan, PancakeRouter swaps, BIGFI burn, and PancakePair sync.
The code-level breakpoint is the BIGFI _burn implementation:
function balanceOf(address account) public view override returns (uint256) {
if (_isExcluded[account]) return _tOwned[account];
return tokenFromReflection(_rOwned[account]);
}
function tokenFromReflection(uint256 rAmount) public view returns(uint256) {
require(rAmount <= _rTotal, "Amount must be less than total reflections");
uint256 currentRate = _getRate();
return rAmount.div(currentRate);
}
function _burn(address _addr, uint256 _value) private {
require(_value <= _rOwned[_addr]);
_rOwned[_addr] = _rOwned[_addr].sub(_value);
_tTotal = _tTotal.sub(_value);
emit Transfer(_addr, dead, _value);
}
Origin: verified BIGFI contract source.
4. Detailed Root Cause Analysis
Immediately before the exploit transaction, the public pre-state included three critical conditions: the flash-loan pool held ample USDT liquidity, the BIGFI/USDT Pancake pair held both USDT and BIGFI reserves, and BIGFI total supply was still the large pre-exploit value above 2.0999e25. The collected balance diff shows the exploit contract started the transaction with 0 USDT and ended with 30306095832979875922923 USDT, so the profit predicate is fully grounded in state changes rather than inference.
The exploit begins by borrowing 200000000000000000000000 USDT from SwapFlashLoan. That USDT is swapped through PancakeRouter into BIGFI, leaving the exploit contract with 5869494994603961621184 BIGFI and the pair with 3259991321231734828254 BIGFI according to the trace. At this point the attacker does not own the 20999908387035301038233370 BIGFI that they are about to burn in nominal units, but the broken _burn guard compares that value to _rOwned[attacker], not to balanceOf(attacker), so the call succeeds.
The critical accounting break happens here:
_burnsubtracts the nominal input from_rOwned[attacker]._burnsubtracts the same nominal input from_tTotal._burndoes not reduce_rTotal.
That combination sharply increases the ratio currentRate = rSupply / tSupply. Since balanceOf(account) returns _rOwned[account] / currentRate, every non-excluded reflected holder suddenly appears to own far fewer BIGFI tokens. The trace shows the pair's BIGFI balance dropping from 3259991321231734828254 to 1 immediately after the burn, while the attacker still controls 3 BIGFI. No transfer removed the pair's reflected balance; the visible balance changed because the reflection conversion was corrupted.
The trace captures the pivot from accounting corruption to pool drain:
DxBurnToken::burn(20999908387035301038233370)
emit Transfer(from: attacker_contract, to: 0x000000000000000000000000000000000000dEaD, value: 20999908387035301038233370)
DxBurnToken::balanceOf(PancakePair) -> 1
PancakePair::sync()
emit Sync(reserve0: 307480664198219600542112, reserve1: 1)
PancakeRouter::swapExactTokensForTokensSupportingFeeOnTransferTokens(3, 0, [BIGFI, USDT], attacker_contract, ...)
emit Transfer(from: PancakePair, to: attacker_contract, value: 230466095832979875922923)
Origin: collected seed trace for tx 0x9fe19093a62a7037d04617b3ac4fbf5cb2d75d8cb6057e7e1b3c75cbbd5a5adc.
After sync(), PancakePair stores reserves of 307480664198219600542112 USDT and 1 BIGFI. That false reserve ratio lets the attacker sell 3 BIGFI for 230466095832979875922923 USDT in a standard router swap. The flash loan is then repaid with the required 160000000000000000000 USDT fee, proving the sequence is self-contained and permissionless. The exploit contract finishes with 30306095832979875922923 USDT, while the sender EOA pays 3336685200000000 wei in gas, yielding a net adversary-cluster delta of 30305005883562115625965 USDT-equivalent under the valuation recorded in root_cause.json.
5. Adversary Flow Analysis
The adversary strategy is a single-transaction flash-loan-assisted reserve distortion and backswap.
SwapFlashLoan::flashLoan(attacker_contract, USDT, 200000000000000000000000, 0x00)
PancakeRouter::swapExactTokensForTokensSupportingFeeOnTransferTokens(USDT -> BIGFI)
DxBurnToken::burn(20999908387035301038233370)
PancakePair::sync()
PancakeRouter::swapExactTokensForTokensSupportingFeeOnTransferTokens(BIGFI -> USDT)
BEP20USDT::transfer(SwapFlashLoan, 200160000000000000000000)
Origin: collected seed trace for the exploit transaction.
The transaction sender was EOA 0x76a88c2baebf251701435abbe8af11ad52b0ab04. The exploit logic ran inside contract 0x1a14ccc8f353d16582c0dfab907481b218475959, which received the flash loan, performed the swaps, called the vulnerable burn, synchronized the pair, and retained the profit.
Step-by-step, the flow is:
SwapFlashLoan.flashLoantransfers200000000000000000000000USDT to the exploit contract and expects200160000000000000000000USDT back.- The exploit contract approves PancakeRouter
0x10ed43c718714eb63d5aa57b78b54704e256024eand swaps the borrowed USDT into BIGFI. - The exploit contract reads
totalSupply,balanceOf(pair), andbalanceOf(self)to derive a target supply that leaves the pair with one visible BIGFI and the attacker with at least three visible BIGFI after the broken burn. - The exploit contract calls BIGFI
burnwith20999908387035301038233370, which is enough to collapse BIGFI total supply to12800. - The exploit contract calls PancakePair
sync(), fixing the manipulated visible balances as official reserves. - The exploit contract swaps its remaining
3BIGFI back into USDT, withdrawing230466095832979875922923USDT from the pair. - The exploit contract repays the flash-loan principal plus fee and keeps
30306095832979875922923USDT.
This sequence is feasible for any unprivileged actor because every call target in the transaction is public and the exploit requires only chain-observable state plus temporary liquidity.
6. Impact & Losses
The measurable victim-side loss is the USDT drained from the BIGFI/USDT Pancake pair. The collected balance diff shows the pair's USDT balance decreased from 107480664198219600542112 to 77014568365239724619189, a loss of 30466095832979875922923 USDT units. BIGFI reserves were also corrupted: the pair's visible BIGFI reserve ended at 4, leaving the market permanently mispriced and effectively drained of usable liquidity.
The exploit contract retained 30306095832979875922923 USDT after the flash-loan repayment, and the flash-loan pool earned 160000000000000000000 USDT in fees. Gas paid by the sender EOA was 3336685200000000 wei, which the updated root-cause artifact values at 1089949417760296958 USDT-equivalent using the on-chain USDT/WBNB pair at the exploit block. On a net basis, the adversary cluster realized 30305005883562115625965 USDT-equivalent profit.
7. References
- Exploit transaction on BNB Smart Chain:
0x9fe19093a62a7037d04617b3ac4fbf5cb2d75d8cb6057e7e1b3c75cbbd5a5adc - Victim token contract: BIGFI
0xd3d4b46db01c006fb165879f343fc13174a1ceeb - Victim liquidity pool: PancakePair BIGFI/USDT
0xa269556edc45581f355742e46d2d722c5f3f551a - Flash-loan pool:
0x28ec0b36f0819ecb5005cab836f4ed5a2eca4d13 - Router used in the exploit: PancakeRouter
0x10ed43c718714eb63d5aa57b78b54704e256024e - Evidence used for validation: collected transaction metadata, full verbose trace, balance-diff artifact, verified BIGFI source, and the verified PancakePair source page on BscScan