Deflationary tokens — tokens that automatically burn supply on transfer — remain one of the most dangerous design patterns in DeFi. In February 2026 alone, flawed burn mechanisms cost protocols over $300K across BNB Chain, with the LAXO token ($190K) and PancakeSwap STO-WBNB pool ($16K) exploits demonstrating that developers keep making the same mistakes.
This guide breaks down exactly why these exploits work, provides vulnerable and secure code patterns, and gives you a concrete checklist to audit any deflationary token.
The Core Problem: Burns That Change Pool Ratios
Every deflationary token exploit follows the same playbook:
- Identify a token where transfers to the LP pool trigger burns from pool reserves
- Flash loan a large amount of the paired asset
- Trigger the burn mechanism to artificially reduce token supply in the pool
- Swap at the manipulated price for profit
- Repay the flash loan
The fundamental issue is simple: if sending tokens to a pool burns tokens from that pool, you've created a price oracle you can manipulate in a single transaction.
Anatomy of the LAXO Exploit (February 22, 2026)
The LAXO token on BNB Chain had a transfer function that checked if the recipient was the PancakeSwap pair address. When it was, tokens were burned from the pool's balance:
// ❌ VULNERABLE: The LAXO pattern
function _transfer(address from, address to, uint256 amount) internal {
// ...
if (to == pancakePair) {
// Burns tokens FROM THE POOL when tokens are sent TO the pool
uint256 burnAmount = amount * burnRate / 100;
_burn(pancakePair, burnAmount);
}
// ...
}
The attacker's exploit flow:
- Flash-borrowed USDT from PancakeSwap
- Bought LAXO tokens
- Transferred LAXO directly to the pair contract (triggering the burn)
- Called
sync()to update reserves to reflect the burned tokens - Swapped remaining LAXO back for USDT at the inflated price
- Repaid flash loan with profit
Total damage: ~$190,540 in a single transaction.
The STO-WBNB Pool Exploit (February 23, 2026)
The STO token had a similar flaw — its burn mechanism activated when the pool was the transfer recipient, reducing pool-side supply and skewing the constant product formula:
// ❌ VULNERABLE: Pool-triggered burns
function transfer(address recipient, uint256 amount) public returns (bool) {
if (recipient == uniswapV2Pair && !isExcluded[msg.sender]) {
uint256 burnFee = amount * 3 / 100;
_totalSupply -= burnFee;
_balances[uniswapV2Pair] -= burnFee;
emit Transfer(uniswapV2Pair, address(0), burnFee);
}
_balances[msg.sender] -= amount;
_balances[recipient] += amount;
return true;
}
Damage: ~$16,100.
Why This Pattern Is Fundamentally Broken
The constant product formula in AMMs like Uniswap/PancakeSwap is:
x * y = k
When you burn tokens from the pool without a corresponding trade, you reduce x while k stays the same (until sync() or the next trade). This means:
If x decreases → y must increase to maintain k
→ The token price (y/x) increases artificially
The attacker exploits the delta between the manipulated price and the true market price.
Secure Deflationary Token Patterns
Pattern 1: Burn from Sender, Not Pool
// ✅ SECURE: Burns come from the sender's transfer amount
function _transfer(address from, address to, uint256 amount) internal {
uint256 burnAmount = amount * burnRate / 100;
uint256 transferAmount = amount - burnAmount;
_balances[from] -= amount;
_balances[to] += transferAmount;
_totalSupply -= burnAmount;
emit Transfer(from, to, transferAmount);
emit Transfer(from, address(0), burnAmount);
}
The burn reduces what the recipient gets, not what the pool already holds. The pool's reserves change only by the actual transfer amount.
Pattern 2: Exclude Pool from Burn Mechanics
// ✅ SECURE: Pool interactions don't trigger burns
mapping(address => bool) public isExcludedFromBurn;
constructor() {
isExcludedFromBurn[pancakePair] = true;
isExcludedFromBurn[uniswapPair] = true;
}
function _transfer(address from, address to, uint256 amount) internal {
uint256 burnAmount = 0;
if (!isExcludedFromBurn[from] && !isExcludedFromBurn[to]) {
burnAmount = amount * burnRate / 100;
}
uint256 transferAmount = amount - burnAmount;
_balances[from] -= amount;
_balances[to] += transferAmount;
if (burnAmount > 0) {
_totalSupply -= burnAmount;
emit Transfer(from, address(0), burnAmount);
}
emit Transfer(from, to, transferAmount);
}
Pattern 3: Dead Address Burns (Safest)
// ✅ SECURE: "Burns" go to a dead address — supply tracking stays consistent
address constant DEAD = 0x000000000000000000000000000000000000dEaD;
function _transfer(address from, address to, uint256 amount) internal {
uint256 burnAmount = amount * burnRate / 100;
uint256 transferAmount = amount - burnAmount;
_balances[from] -= amount;
_balances[to] += transferAmount;
_balances[DEAD] += burnAmount;
emit Transfer(from, to, transferAmount);
emit Transfer(from, DEAD, burnAmount);
// totalSupply unchanged — "burned" tokens are just permanently locked
}
The Sync() Trap
Even if your burn mechanism looks safe, calling IUniswapV2Pair(pair).sync() after manipulating balances is a red flag:
// ❌ DANGEROUS: Any function that externally calls sync() after balance changes
function deflate() external {
_burn(pancakePair, deflationAmount);
IUniswapV2Pair(pancakePair).sync();
// Attacker can now swap at manipulated price
}
Rule: Never expose a public function that burns from a pool and syncs in the same transaction.
Solana Equivalent: SPL Token Burn Authority Risks
On Solana, the equivalent risk comes from Token-2022's burn authority and close authority:
// ❌ VULNERABLE: Unrestricted burn authority on pool token accounts
pub fn process_deflation(ctx: Context<Deflation>) -> Result<()> {
token::burn(
CpiContext::new(
ctx.accounts.token_program.to_account_info(),
Burn {
mint: ctx.accounts.mint.to_account_info(),
from: ctx.accounts.pool_token_account.to_account_info(),
authority: ctx.accounts.burn_authority.to_account_info(),
},
),
deflation_amount,
)?;
Ok(())
}
Defense: Never grant burn authority over LP pool token accounts. Use transfer hooks for deflationary mechanics instead.
// ✅ SECURE: Transfer hook that reduces received amount
pub fn transfer_hook(ctx: Context<TransferHook>, amount: u64) -> Result<()> {
let burn_amount = amount * burn_rate / 10000;
msg!("Deflation burn: {} tokens", burn_amount);
Ok(())
}
Security Audit Checklist for Deflationary Tokens
1. Burn Source Verification
- [ ] Burns deduct from the transfer amount, not from pool balances
- [ ] No function can burn tokens directly from LP pair addresses
- [ ]
totalSupplychanges are consistent with actual balance changes
2. Pool Interaction Safety
- [ ] LP pair addresses are excluded from special transfer logic, OR
- [ ] Special logic only affects the transfer amount (not existing balances)
- [ ] No public function combines balance manipulation with
sync()
3. Access Control
- [ ] Burn rate cannot be changed to 100% (rug vector)
- [ ] Pool exclusion list is immutable or behind a timelock
- [ ] No admin function can drain pool reserves via "emergency burn"
4. Flash Loan Resistance
- [ ] Price impact of maximum single-transaction burn is < 1%
- [ ] Protocol uses TWAP oracles, not spot prices, for any price-dependent logic
- [ ] Rate limiting exists on burn-triggering transfers
5. Integration Safety
- [ ] Token behaves correctly with
transferFrom(allowance + burn interaction) - [ ] Fee-on-transfer is documented for DEX/lending protocol integrators
- [ ] Reflection/rebase mechanics don't compound with burns unexpectedly
Key Takeaways
Never burn from pool balances. If your burn mechanism can reduce tokens in an LP pool outside of a normal swap, it's exploitable.
Dead address > supply reduction. Sending "burned" tokens to
0xdeadis safer than reducingtotalSupplybecause it can't create accounting mismatches.Exclude AMM pairs from special logic. Unless you have a very specific reason (and an audit to back it up), AMM pool addresses should be excluded from tax/burn/reflection mechanics.
Test with flash loans. Before deployment, write a test that flash-borrows the maximum available liquidity and attempts to profit from your burn mechanism. If the test profits, you have a vulnerability.
On Solana, never grant burn authority over pool accounts. Use transfer hooks for deflationary mechanics instead.
This is part of our ongoing Smart Contract Security Research series. Follow for weekly deep dives into real exploits and defensive patterns.
Have a deflationary token you'd like reviewed? Drop a comment with the contract address.
Top comments (0)