All incidents

SafeMoon LP Burn Drain

Share
Mar 28, 2023 19:26 UTCAttackLoss: 28,355.85 WBNBPending manual check1 exploit txWindow: Atomic
Estimated Impact
28,355.85 WBNB
Label
Attack
Exploit Tx
1
Addresses
2
Attack Window
Atomic
Mar 28, 2023 19:26 UTC → Mar 28, 2023 19:26 UTC

Exploit Transactions

TX 1BSC
0x48e52a12cb297354a2a1c54cbc897cf3772328e7e71f51c9889bb8c5e533a934
Mar 28, 2023 19:26 UTCExplorer

Victim Addresses

0x42981d0bfbaf196529376ee702f2a9eb9092fcb5BSC
0x8e0301e3bde2397449fef72703e71284d0d149f1BSC

Loss Breakdown

28,355.85WBNB

Similar Incidents

Root Cause Analysis

SafeMoon LP Burn Drain

1. Incident Overview TL;DR

On BNB Smart Chain block 26864890, transaction 0x48e52a12cb297354a2a1c54cbc897cf3772328e7e71f51c9889bb8c5e533a934 let attacker EOA 0x286e09932b8d096cba3423d12965042736b8f850 use helper contract 0xa1fae685c8abf938eb706dedabbcffbff3b3d7da to flash-borrow WBNB, buy SafeMoon, destroy almost all SFM held by the SafeMoon/WBNB pool, call sync(), and then sell back into the manipulated pool. The transaction repaid the flashloan and increased the attacker EOA's native balance by 27387357095483374950933 wei, already net of gas.

The root cause is a permissionless authorization failure in SafeMoon. The SafeMoon exploit path exposed burn(address from, uint256 amount) as a public arbitrary-from balance mutation primitive, so any caller could confiscate SFM from third-party addresses such as the SafeMoon/WBNB pair 0x8e0301e3bde2397449fef72703e71284d0d149f1 or the token contract itself. Once the pair's SFM balance was reduced to dust and the pair was synced, the attacker could drain nearly all WBNB liquidity at the distorted price.

2. Key Background

SafeMoon was called through proxy 0x42981d0bfbaf196529376ee702f2a9eb9092fcb5. In the exploit trace, the burn path delegatecall resolves to code artifact 0xeb11a0a0bef1ac028b8c2d4cd64138dd5938ca7a, which contains the vulnerable burn(address,uint256) implementation. The collected balance-diff artifact also attributes SafeMoon storage layout to the verified SafeMoon codebase used for the exploit.

The affected liquidity venue was the SafeSwap pair proxy 0x8e0301e3bde2397449fef72703e71284d0d149f1, whose implementation 0x35e072e93b2e4316e3bb0ef4cda4eb206188afeb uses the standard AMM sync() pattern: reserves are overwritten with the pair's current token balances. That matters because SafeMoon's arbitrary-from burn can change the pair's SFM balance without going through pair logic; sync() then crystallizes that manipulated balance into AMM pricing.

SafeMoon transfer logic also contains automatic contract-held-token conversion to BNB when the token contract balance exceeds numTokensToCollectBNB. The attacker avoided that side effect by burning the SafeMoon contract's own SFM balance before the final sell, so the monetization leg was not disrupted by an internal collectBNB() path.

The entire sequence is permissionless. The attacker needed only an unprivileged EOA, a helper contract, a public flashloan source, and public liquidity venues. No private key compromise, privileged role, or attacker-specific contract artifact was required.

3. Vulnerability Analysis & Root Cause Summary

This is an ATTACK case caused by missing authorization on a privileged token-balance mutation primitive. SafeMoon's code lets any caller invoke burn(address from, uint256 amount) and pass an arbitrary third-party from address, but it does not enforce ownership, allowance, bridge-role, or sender-binding checks before moving tokens out of that address. The function immediately routes into _tokenTransfer, which subtracts balance from from and transfers the value to the configured burn sink with fees disabled. That breaks the core safety invariant that only the token holder, an approved spender, or an explicitly authorized privileged role should be able to reduce another account's SFM balance. Because the SafeMoon/WBNB pair holds SFM inventory directly, the attacker can burn pool inventory externally and then use sync() to force the AMM to accept the manipulated reserve state. Once reserves are skewed, previously acquired SFM can be sold back into the pool for nearly all of its WBNB. The same primitive also lets the attacker remove SFM held by the SafeMoon contract itself, preventing the contract's own swapback path from interfering with the exit.

Collected code evidence shows the defect directly:

function burn(address from, uint256 amount) public {
    _tokenTransfer(from, bridgeBurnAddress, amount, 0, false);
}

function _tokenTransfer(
    address sender,
    address recipient,
    uint256 amount,
    uint256 tierIndex,
    bool takeFee
) private {
    if (!takeFee) removeAllFee();
    ...
}

The corresponding AMM-side reserve commit is standard:

function sync() external lock {
    _update(
        IERC20(token0).balanceOf(address(this)),
        IERC20(token1).balanceOf(address(this)),
        reserve0,
        reserve1
    );
}

4. Detailed Root Cause Analysis

The ACT opportunity existed in the public BSC pre-state immediately before transaction index 0 of block 26864890. At that point the SafeMoon proxy and SafeSwap pair proxy were deployed and reachable, the SafeMoon burn path remained publicly callable, and the SafeMoon/WBNB pair held large balances of both assets. The collected oracle pre-checks and exploit metadata confirm that the pair held well above the residual SFM floor and more than 20000 WBNB before exploitation.

The exploit transaction is a single adversary-crafted transaction. It bundles flashloan funding, initial SFM accumulation, unauthorized reserve destruction, reserve synchronization, final monetization, and flashloan repayment. The inclusion feasibility is straightforward: every primitive in the path is public and does not depend on attacker-specific privilege.

The code-level breakpoint is the call to burn(address from, uint256 amount) with from set to third-party addresses that never approved the attacker. In the trace, the attacker helper calls SafeMoon twice through the proxy path: first with the pair as from, then with the SafeMoon token contract itself as from. The trace records the decisive state transitions:

TransparentUpgradeableProxy::fallback(OptimizedTransparentUpgradeableProxy: [0x8e0301E3bDE2397449FeF72703E71284d0d149F1], 31880230380377600608)
  Safemoon::burn(OptimizedTransparentUpgradeableProxy: [0x8e0301E3bDE2397449FeF72703E71284d0d149F1], 31880230380377600608) [delegatecall]
    emit Transfer(from: OptimizedTransparentUpgradeableProxy: [0x8e0301E3bDE2397449FeF72703E71284d0d149F1], to: 0x678ee23173dce625A90ED651E91CA5138149F590, value: 31880230380377600608)

TransparentUpgradeableProxy::fallback(TransparentUpgradeableProxy: [0x42981d0bfbAf196529376EE702F2a9Eb9092fcB5], 31361873472705444)
  Safemoon::burn(TransparentUpgradeableProxy: [0x42981d0bfbAf196529376EE702F2a9Eb9092fcB5], 31361873472705444) [delegatecall]
    emit Transfer(from: TransparentUpgradeableProxy: [0x42981d0bfbAf196529376EE702F2a9Eb9092fcB5], to: 0x678ee23173dce625A90ED651E91CA5138149F590, value: 31361873472705444)

0x35e072E93B2e4316e3bb0ef4cDA4Eb206188afEb::sync() [delegatecall]
  emit Sync(reserve0: 1000000000, reserve1: 28355958285296037562844)

The collected receipt and stage analysis show how those calls fit together:

  1. The helper contract flash-borrows 1000 WBNB from Pancake pair 0x1cea83ec5e48d9157fcae27a19807bef79195ce1.
  2. It spends 897750000000000000000 raw WBNB to buy 936219582028406323 raw SFM from the SafeMoon/WBNB pair. After that buy leg, the pair holds 31880230381377600608 raw SFM and 28355958285296037562844 raw WBNB.
  3. It calls the public SafeMoon burn path against the pair and removes 31880230380377600608 raw SFM, leaving only 1000000000 raw SFM in the pair. It then burns 31361873472705444 raw SFM from the SafeMoon contract itself.
  4. It calls sync(), which rewrites the pair reserves to the manipulated live balances: 1000000000 raw SFM and 28355958285296037562844 raw WBNB.
  5. It sells the attacker's remaining SFM into the now-mispriced pool, receives 28355853053089548067627 raw WBNB, repays 1005000000000000000000 raw WBNB to the flashloan pair, and leaves the attacker EOA with a net native-balance increase of 27387357095483374950933 wei.

The balance-diff artifact independently confirms the economic effect. The attacker EOA starts at 26715964141122306445 wei and ends at 27414073059624497257378 wei, for a delta of 27387357095483374950933 wei. The same artifact shows the SafeMoon/WBNB pair losing essentially all of its SFM inventory and the WBNB-bearing side of the system losing 28355853053089548067627 units of value.

The exploit conditions listed by the auditor are also supported by evidence. The public burn primitive had to remain exposed, the target address had to hold SFM, meaningful WBNB liquidity had to exist in the pair, and the attacker benefited from clearing the SafeMoon contract's own balance to suppress swapback behavior during the exit. None of those conditions required privileged access.

5. Adversary Flow Analysis

The adversary strategy is a single-transaction, flashloan-backed reserve distortion attack.

The adversary cluster identified in the collected artifacts is:

  • EOA 0x286e09932b8d096cba3423d12965042736b8f850, which sends the exploit transaction and receives the net profit.
  • Helper contract 0xa1fae685c8abf938eb706dedabbcffbff3b3d7da, which executes the flashloan callback, swaps, burns, sync(), sale, and repayment.

The victim-side components are:

  • SafeMoon proxy 0x42981d0bfbaf196529376ee702f2a9eb9092fcb5.
  • SafeSwap pair proxy 0x8e0301e3bde2397449fef72703e71284d0d149f1.

The execution flow is:

  1. Flashloan and initial buy. The helper contract receives 1000 WBNB from the Pancake pair and uses most of it to buy SFM through SafeSwap, ending the first leg with a sizeable SFM position and a still-deep WBNB pool.
  2. Unauthorized reserve destruction. The helper calls SafeMoon's public burn(address,uint256) with the pair as from, destroying nearly the entire SFM side of the pool. It then repeats the same primitive against the SafeMoon contract address to clear contract-held SFM that would otherwise trigger internal swapback logic.
  3. Reserve commit. The helper calls sync() on the SafeSwap pair so the manipulated SFM balance becomes the official reserve state.
  4. Monetization. The helper sells its remaining SFM into a pool that still has almost all of its WBNB but now advertises only dust SFM reserves, causing an enormous WBNB payout.
  5. Repayment and profit realization. The flashloan principal plus fee is returned inside the same transaction, and the residual value ends at the attacker EOA as net BNB profit.

This sequence matches the ACT framing exactly. The adversary-crafted transaction realizes the success predicate with public information and public contract entrypoints only; the victim-observed side effects are the collapse of pair SFM reserves, the collapse of pair WBNB reserves after the final sale, and the attacker's profit.

6. Impact & Losses

The primary measurable loss is the depletion of WBNB from the SafeMoon/WBNB pair. After the burn-and-sync step, the pair held 28355958285296037562844 raw WBNB. After the attacker sold back into the distorted pool, the pair held only 105232206489495217 raw WBNB. That is a depletion of 28355853053089548067627 raw WBNB.

The attacker EOA's native balance increased by 27387357095483374950933 wei after gas. The root-cause artifact correctly notes that this native delta is already net of gas and that the flashloan principal and repayment are internalized inside the same transaction, so the profit figure is already a usable end-state success predicate.

The vulnerable components and security principles violated are clear:

  • Missing authorization on a privileged token-balance mutation primitive.
  • Broken separation between bridge or supply-management logic and user-held or LP-held balances.
  • Failure to preserve AMM reserve integrity against external confiscation of token-side reserves.

7. References

  1. Exploit transaction 0x48e52a12cb297354a2a1c54cbc897cf3772328e7e71f51c9889bb8c5e533a934 on BNB Smart Chain, including collected metadata and receipt.
  2. Collected verbose execution trace for the exploit transaction, which shows the two unauthorized SafeMoon burns, the sync() call, the final sale, and the flashloan repayment.
  3. Collected balance-diff artifact for the exploit transaction, which shows the attacker EOA profit and the pair-side asset depletion.
  4. Collected SafeMoon exploit-path source code for 0xeb11a0a0bef1ac028b8c2d4cd64138dd5938ca7a, especially burn(address,uint256) and _tokenTransfer.
  5. Collected SafeSwap pair implementation source for 0x35e072e93b2e4316e3bb0ef4cda4eb206188afeb, especially sync().
  6. Root-cause summary fields in root_cause.json, including the ACT pre-state definition, exploit conditions, adversary account clustering, and loss summary.
SafeMoon LP Burn Drain | Clara