DxSale runs liquidity lockers on BNB Chain: token teams lock their LP tokens there to show buyers the liquidity cannot be pulled. In late May 2026 those lockers were emptied. Rekt counts $7.3M drained from the primary locker across more than 1,400 pools1. PeckShield traced about 2,958 BNB, roughly $1.87M, to two attacker wallets2.
The drain was fast. The warning was not. The lockers changed owner almost two days before, in three public transactions. This post shows the timeline and what an alert on that change would have bought.
How the lockers were controlled
Each locker is an Ownable contract. Its owner can call admin functions, and those functions could move the locked LP tokens1.
- Primary locker:
0xEb3a…e449 - Locker 2:
0x2D04…E677 - Locker 3:
0x81E0…334d - Original owner:
0x47BA…B78b
SlowMist classes the cause as a leaked private key3. DxSale blamed BSC atomic transactions; Rekt disputes that1. DxSale has not published a post-mortem. We do not guess how the key leaked.
The attack, step by step
All times UTC. We read the block time of every transaction below over public BNB Chain RPC4.
May 26, 01:08:21 — locker 2 changes owner
The original owner called transferOwnership on locker 2 and handed it to 0xC457…FA69 (0xeb24…57a0).
This is the first on-chain signal.
01:08:56 — the primary locker
35 seconds later, the same for the primary locker (0x23e3…8d41).
01:14:21 — locker 3
Six minutes later, locker 3 (0xdfda…19f3).
Three ownership changes on three lockers within six minutes, to the same new address with no history, at 1 a.m. UTC. There is no innocent reading of that.
May 27, 20:57:54 — the new owner gets gas
The new owner received BNB for gas (0xffc7…b72a). Rekt says the funds came from Bybit1; we did not verify the source. A wallet that held three lockers for 43 hours without moving now had gas.
May 27, 22:37:45 onward — the drain
The new owner started pulling LP tokens out of the lockers. An example: 0xb107…5fe9. Liquidity removals followed through the night, for example at 04:26:05 on May 28 (0xb0ee…4459). We did not establish which transaction was the very first drain, so we give these as examples.
The first public alert came from an on-chain researcher in the early hours of May 285, after the drain had started. DxSale's first statement came on May 296.
From the first owner change to the example drain: 45 hours 29 minutes.
Who else could have seen it
Locker ownership is public. Any team whose LP tokens sat in DxSale could have watched OwnershipTransferred on the locker holding them, without DxSale's permission. A monitor on someone else's contract is legitimate when your money sits in it.
What no rule would have changed
How to set up these rules in SmartAlert
- Add every contract with an owner that can move funds: lockers, vaults, treasuries, bridges.
- Create an Ownership transferred rule on each, any event, Critical.
- If your LP or tokens sit in someone else's locker, add that locker too. No ownership proof is needed to watch a public contract.
- Add a Transfer above $X rule with
from= the locker, for the drain itself. - Agree in advance who announces a compromise and through which channel. Alerts give time; a plan uses it.
See all alert recipes and the post-audit checklist.
Sources
- 1.Rekt, DxSale — Rekt: lockers, ownership transfer, $7.3M drained, Bybit funding, dispute with DxSale's explanation. ↩
- 2.PeckShield on X, trace of 2,958 BNB. ↩
- 3.GoPlus on X, incident note; ExVul on X, incident note. SlowMist classification as cited by Rekt. ↩
- 4.Checked by SmartAlert on-chain: block times, senders and targets of every transaction in this post, over public BNB Chain RPC. ↩
- 5.Tahax on X, first public alert. ↩
- 6.DxSale on X, statements of May 29 and May 30. ↩