Calculated from recorded token losses using historical USD prices at the incident time.
0x2fcee04e64e54f3dd9c15db9ae44e4cbdd57ab4c6f01941a3acf470dc60bfc160x2d9ffa7ea5d1aaaba58e60168517b49f57e7f85bBSC0x7dda132dd57b773a94e27c5caa97834a73510429BSCOn BSC block 34402344, transaction 0x2fcee04e64e54f3dd9c15db9ae44e4cbdd57ab4c6f01941a3acf470dc60bfc16 exploited KEKESANTA token 0x7dda132dd57b773a94e27c5caa97834a73510429 and economically harmed the KEKESANTA/WBNB Pancake pair 0x2d9ffa7ea5d1aaaba58e60168517b49f57e7f85b. The adversary used only public infrastructure: a flash-loan source, Pancake router 0x10ed43c718714eb63d5aa57b78b54704e256024e, Pancake pair logic, and the token's public transfer paths.
The root cause is a transfer-accounting bug in KEKESANTA. Its _transfer routine treats isMarket(from) and isMarket(to) as separate if branches rather than mutually exclusive modes. When a transfer is routed from the Pancake pair to the Pancake router, both conditions are true, so the sender is debited once but the recipient and fee wallet are credited twice. That creates extra KEST without changing totalSupply, lets the attacker recycle the duplicated tokens through public router flows, and drains WBNB from the pair.
KEKESANTA hard-codes two addresses as market endpoints: the Pancake router and the KEKESANTA/WBNB pair. That classification matters because the token charges different fees when from is a market versus when to is a market. The implementation assumes those cases are mutually exclusive, but Pancake routing legitimately creates transfers where the pair sends tokens to the router.
Two public Pancake paths are especially important:
swapTokensForExactTokens(..., to=router) causes the pair to send output tokens directly to the router.removeLiquidityETHSupportingFeeOnTransferTokens(...) calls PancakePair::burn(router), which also sends pair assets to the router.Those pair-to-router transfers are normal Pancake behavior. The problem is that KEKESANTA's transfer logic misprices them and mints accounting-only KEST along the way.
The vulnerability class is a broken token-accounting implementation in a fee-on-transfer token integrated with a DEX. KEKESANTA snapshots the sender balance once, then separately processes a buy-fee branch and a sell-fee branch. If both endpoints are markets, both branches execute against the same cached sender balance.
The relevant code in KEKESANTA is:
uint256 fromBalance = _balances[from];
if (isMarket(from)) {
uint fee = takeAFee(amount, buyFee);
_balances[from] = fromBalance - amount;
_balances[to] += amount - fee;
_balances[marketWallet] += fee;
}
if (isMarket(to)) {
uint fee = takeAFee(amount, sellFee);
_balances[from] = fromBalance - amount;
_balances[to] += amount - fee;
_balances[marketWallet] += fee;
}
This violates the token-balance conservation invariant: for a normal transfer, the sender debit plus the recipient credit plus fee credit must net to zero unless explicit mint or burn logic updates supply. Here, totalSupply stays fixed, but the recipient and fee wallet are credited twice while the sender ends at only fromBalance - amount. The result is synthetic KEST that the attacker can sell or turn into LP value.
The bug sits in KEKESANTA::_transfer. KEKESANTA defines isMarket(user) as true when user is either the Pancake router or the Pancake pair. That means a pair-to-router transfer satisfies both isMarket(from) and isMarket(to).
function isMarket(address user) internal view returns (bool) {
if (user == address(_router) || user == address(_pair)) {
return true;
} else {
return false;
}
}
Pancake's pair contract legitimately emits exactly those transfers during swap and burn paths:
function burn(address to) external lock returns (uint amount0, uint amount1) {
...
_safeTransfer(_token0, to, amount0);
_safeTransfer(_token1, to, amount1);
...
}
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
...
if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out);
if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out);
...
}
So the invariant break is deterministic:
_transfer(pair, router, amount).fromBalance.amount once, but the router and market wallet each receive two credits.The seed trace shows the exploit contract taking a public flash loan of 200 WBNB, then executing the market-to-market cycle through router and pair calls. Representative trace events include:
0xd50Cf00b6e600Dd036Ba8eF475677d816d6c4281::flashLoan(..., [200000000000000000000], ...)
PancakeRouter::swapTokensForExactTokens(334886494892597876400352453291, 199368246265042846651, [...], PancakeRouter, ...)
PancakeRouter::removeLiquidityETHSupportingFeeOnTransferTokens(KEKESANTA, 1000000000000000, 1, 1, 0xC25979956D6f6AcFc3702C68DFf7a4d871Eee4aa, ...)
PancakePair::burn(PancakeRouter)
WBNB::transfer(0x90c4C1aa895a086215765EC9639431309633B198, 9019657610212775442)
PancakePair::transfer(0x90c4C1aa895a086215765EC9639431309633B198, 2146320284844256899722)
The sequence is important. The attacker does not need privileged functions, fee exemptions, attacker-specific bytecode, or private orderflow. Public interfaces are enough:
The sender EOA 0x90c4c1aa895a086215765ec9639431309633b198 had 989051348300000000 wei native BNB before the exploit and 971767348300000000 wei native BNB after it. The same transaction also transferred 9019657610212775442 wei WBNB to that EOA. Treating BNB and WBNB as 1:1 on BSC gives a deterministic lower-bound post-state portfolio value of 9991424958512775442 wei.
After subtracting the 17284000000000000 wei gas cost, the EOA realized a lower-bound gain of 9002373610212775442 wei. That lower bound excludes the 2146320284844256899722 Pancake LP tokens transferred to the EOA and the 26329693359224618059986 LP tokens retained by the exploit contract, so it understates the full economic result.
The identified adversary cluster is:
0x90c4c1aa895a086215765ec9639431309633b198, which submitted the exploit transaction and received final payouts.0xc25979956d6f6acfc3702c68dff7a4d871eee4aa, which executed the exploit logic in-transaction.The exploit unfolded in three stages.
The exploit contract borrowed 200 WBNB, used a small 0.01 WBNB buy to acquire KEST, transferred WBNB and KEST into the pair, and minted initial LP. This stage created the first LP foothold needed to access Pancake's public burn path.
The exploit then repeated a router-mediated loop:
Each router-targeted output and burn path generated pair-to-router KEST transfers. Those were the exact transfers that caused both KEKESANTA market branches to execute and break balance conservation.
At the end of the transaction, the exploit contract transferred 9019657610212775442 wei WBNB and 2146320284844256899722 LP tokens to the submitting EOA, and the balance-diff artifact records another 26329693359224618059986 LP tokens at post-state holder 0x0ed943ce24baebf257488771759f9bf482c39706, which the root-cause artifact attributes to the residual exploit path. The flash loan plus fee was then repaid, and the entire exploit completed in one public transaction.
The direct measurable pool loss is 9199657663494314480 raw units of WBNB (9.19965766349431448 WBNB). The balance-diff artifact also shows the pair's KEST balance expanding from 477302959604163425155246829468 to 18597825900069617926618400412389, which confirms that the pool was left holding massively inflated KEST inventory while losing WBNB.
That means the incident harmed LPs in two ways:
The incident is therefore an ACT exploit with concrete economic loss, not a theoretical accounting anomaly.
0x2fcee04e64e54f3dd9c15db9ae44e4cbdd57ab4c6f01941a3acf470dc60bfc16.0x7dda132dd57b773a94e27c5caa97834a73510429, especially _transfer and isMarket.0x2d9ffa7ea5d1aaaba58e60168517b49f57e7f85b, especially swap and burn.