This is a lower bound: only assets with reliable historical USD prices are counted, so the actual loss may be higher.
0x05eabbb665a5b99490510d0b3f93565f394914294ab4d609895e525b43ff16f20x2c25aee99ed08a61e7407a5674bc2d1a72b5d8e3BSC0xb6cf5b77b92a722bf34f6f5d6b1fe4700908935eBSCOn BNB Smart Chain block 27620321, transaction 0x05eabbb665a5b99490510d0b3f93565f394914294ab4d609895e525b43ff16f2 let an unprivileged adversary convert a stale presale quote into immediate on-chain profit. The sender 0xAAA75B2AE8314EF738062Da56E0F09D2d53c43D2 called helper contract 0xD088b5E169301d280129deb981d598A2Fd277b5c, borrowed 32.5 WBNB from public DODO pool 0xFeAFe253802b77456B4627F8c2306a9CeBb5d681, bought 9,750 AXT from AxiomaPresale at 0x2C25aEe99ED08A61e7407A5674BC2d1A72B5D8E3, sold that inventory into Pancake pair 0x6a3Fa7D2C71fd7D44BF3a2890aA257F34083c90f, repaid the flash loan, and retained 20.805274107352437320 WBNB.
The root cause is a permissionless stale-price arbitrage. AxiomaPresale exposed inventory at a fixed 300 AXT per BNB quote with buyTax = 0, while the live AXT/WBNB pool priced AXT materially higher in BNB terms. Because buyToken() is public and performs no market-price or slippage validation, any searcher able to source temporary capital could buy from the presale and atomically resell into the AMM for profit.
AxiomaPresale is a simple sale contract for (). At the exploit pre-state block , public state showed:
AXIOMATOKEN0xB6CF5b77B92a722bF34f6f5D6B1Fe4700908935E27620320300000000000, which yields 300 AXT per 1 BNB.0.9,999,996.16 AXT.14,157.668659303833605910 AXT and 135.484087470763777599 WBNB.Those reserves imply roughly 104.4969 AXT per 1 WBNB in the pool before slippage. The presale therefore sold AXT far more cheaply than the AMM's executable price in BNB terms.
The token contract matters because it charges sell-side transfer fees. The verified AXIOMATOKEN source sets:
rewardsSellFee = 25;
marketingSellFee = 10;
liquiditySellFee = 20;
totalSellFees = rewardsSellFee + marketingSellFee + liquiditySellFee;
With feeDivisor = 1000, that is a 5.5% sell fee. Even after paying that fee and Pancake swap fees, the spread between 300 AXT/BNB at the presale and about 104.5 AXT/BNB at the pool remained strongly profitable.
This is an MEV-class ACT opportunity, not an access-control compromise. The failure is economic: the protocol left public inventory available at a stale fixed quote that could be cleared into a richer public exit venue in the same transaction.
The decisive victim logic is the verified AxiomaPresale.buyToken() implementation:
function buyToken() public payable {
uint256 bnbAmountToBuy = msg.value;
uint256 tokenAmount = bnbAmountToBuy.mul(rate).div(10**9);
require(token.balanceOf(address(this)) >= tokenAmount, "INSUFFICIENT_BALANCE_IN_CONTRACT");
payable(PresaleOwner).transfer(bnbAmountToBuy);
uint256 taxAmount = tokenAmount.mul(buyTax).div(100);
token.transfer(PresaleOwner, taxAmount);
(bool sent) = token.transfer(msg.sender, tokenAmount.sub(taxAmount));
require(sent, "FAILED_TO_TRANSFER_TOKENS_TO_BUYER");
}
The invariant that should have held is straightforward: a public sale contract should not offer inventory at a quote that is strictly worse than the simultaneously executable on-chain market price when buyers can atomically resell into that market. The code-level breakpoint is tokenAmount = bnbAmountToBuy.mul(rate).div(10**9). rate is just an owner-set constant. The function does not read AMM reserves, does not use an oracle, and does not enforce a minimum fair-value bound before releasing tokens.
The root cause is therefore fully deterministic:
buyToken() is permissionless.300 AXT/BNB.Immediately before block 27620321, the public state already contained every ingredient needed for the exploit:
AxiomaPresale.rate() = 300000000000AxiomaPresale.buyTax() = 0AXT.balanceOf(AxiomaPresale) = 999999616000000000000000014157668659303833605910 AXT and 135484087470763777599 WBNBNo private key, whitelist, or privileged method was required to act on that state. The opportunity was observable from public RPC reads alone.
The presale contract makes the sale executable for anyone and forwards the incoming BNB directly to PresaleOwner 0x3B215f124cA1F3c30e00EE4d96D48e604Cdd9026. That means the contract never accumulates BNB collateral that could offset post-sale price movements.
The token's sell-fee logic also matches the incident trace. During the resale leg, 9,750 AXT left the attacker helper, but only 9,213.75 AXT reached the pair and 536.25 AXT was skimmed as fee. That split is exactly 5.5%, which is what the verified token contract encodes for sells into automated market maker pairs.
The seed transaction trace shows the exploit path end to end:
0xFeAFe253802b77456B4627F8c2306a9CeBb5d681::flashLoan(32500000000000000000, ...)
WBNB::withdraw(32500000000000000000)
0x2C25aEe99ED08A61e7407A5674BC2d1A72B5D8E3::buyToken{value: 32500000000000000000}()
0xB6CF5b77B92a722bF34f6f5D6B1Fe4700908935E::transfer(attacker helper, 9750000000000000000000)
0xB6CF5b77B92a722bF34f6f5D6B1Fe4700908935E::transfer(pair, 9750000000000000000000)
0x6a3Fa7D2C71fd7D44BF3a2890aA257F34083c90f::swap(0, 53305274107352437320, attacker helper, 0x)
WBNB::transfer(DODO pool, 32500000000000000000)
WBNB::transfer(attacker EOA, 20805274107352437320)
The corresponding balance deltas confirm the economic result:
AxiomaPresale lost 9,750 AXT.PresaleOwner received 32.5 BNB.9,213.75 AXT after token fees.20.805274107352437320 WBNB.0.01970612 BNB gas, net profit was 20.785567987352437320 BNB equivalent.This shows the incident is not speculative replay logic. It is a real, profitable, single-transaction arbitrage already realized on-chain.
Every leg was permissionless:
AxiomaPresale.buyToken() was public.The opportunity therefore fits the ACT adversary model exactly: any unprivileged actor with normal on-chain capabilities could have reproduced the same buy-low/sell-high sequence.
The adversary flow has three concrete stages.
First, the helper contract borrowed 32.5 WBNB from DODO pool 0xFeAFe253802b77456B4627F8c2306a9CeBb5d681 and unwrapped it to native BNB. That provided temporary capital without requiring upfront treasury.
Second, the helper spent the full 32.5 BNB in AxiomaPresale.buyToken(). Because the rate was fixed at 300 AXT/BNB and buy tax was zero, the helper received exactly 9,750 AXT. In the same call, the presale forwarded the 32.5 BNB to PresaleOwner, so the sale contract took no protective action based on market state.
Third, the helper sold the newly acquired AXT into the public Pancake pair. The token's sell fee reduced the effective input to 9,213.75 AXT, yet the swap still returned 53.305274107352437320 WBNB according to the incident trace. The helper repaid the 32.5 WBNB flash loan and transferred the remaining 20.805274107352437320 WBNB to the sender EOA.
The key decision point was purely economic: the attacker observed that the presale quote remained stale relative to pool reserves. Once that condition existed, the exploit sequence was mechanical.
The measurable on-chain impact was:
9,750 AXT removed from presale inventory, encoded on-chain as 9750000000000000000000.20.805274107352437320 WBNB gross profit captured by the attacker EOA, encoded on-chain as 20805274107352437320.Operationally, the incident drained public sale inventory at an uneconomic quote and transferred value out of the AXT/WBNB pool to the attacker. Gas reduced the sender's net gain to 20.785567987352437320 BNB equivalent, but the exploit remained highly profitable.
0x05eabbb665a5b99490510d0b3f93565f394914294ab4d609895e525b43ff16f20x2C25aEe99ED08A61e7407A5674BC2d1A72B5D8E30xB6CF5b77B92a722bF34f6f5D6B1Fe4700908935E0x6a3Fa7D2C71fd7D44BF3a2890aA257F34083c90f0xFeAFe253802b77456B4627F8c2306a9CeBb5d681rate = 300000000000, and buyTax = 0