Calculated from recorded token losses using historical USD prices at the incident time.
0xcc0f0f41f4c4c17493517dd6c6d9dd1adb134fc9BSC0x4200a9b80b1e84cf94ad8fc28f66195bc3c37f3fBSCOn BSC, an attacker-controlled EOA 0x101723def8695f5bb8d5d4aa70869c10b5ff6340 exploited YYSCoin reward contract 0xcc0f0f41f4c4c17493517dd6c6d9dd1adb134fc9 by first registering a fresh helper contract through a public 100-USDT investment flow, then using a flash-loan-funded transaction to buy YYSCoin and call sell(uint256) eleven times. Each sell call consumed LP tokens owned by the victim reward contract, removed liquidity through PancakeRouter, and routed the resulting assets to the attacker-controlled helper. The exploit transaction 0x397a09af6494c0bfcd89e010f5dd65d90f3ee1cf1ff813ce5b0c1d42a1c8dec9 finished with 28942729962589664590904 raw USDT units credited to the attacker EOA, while the flash lender was repaid and the victim LP balance fell from 137767741348632645921126 to 364589772282315947621.
The root cause is a direct protocol bug. The victim exposes a public sell(uint256) path that spends LP held by the victim contract itself and sends the withdrawn assets to msg.sender. Caller-supplied YYSCoin is treated as sufficient authorization, so any user that first satisfies the public registration gate can convert a small YYSCoin position into unauthorized redemption of protocol-owned liquidity.
YYSCoin token 0xe814cc2b4dbfe652c04f2e008ced18875c76f510 imposes a transfer gate on buys from its internal pair. In the collected source, the _transfer logic checks and requires whenever , so a fresh attacker cannot simply buy YYSCoin from the pair without first becoming a registered reward-system user.
0xfda026b479c5e0070f4eed542b292031f4e077c6917d211820c572ac33842cda0x397a09af6494c0bfcd89e010f5dd65d90f3ee1cf1ff813ce5b0c1d42a1c8dec9ddd.userRewardInfo(to)qq > 0from == innerPairThe attacker solved that requirement through the reward contract's public investment path. The setup replay on a local fork shows that replaying the helper setup call with 0.2 BNB deposits WBNB, swaps into USDT, approves the victim contract, emits victim events consistent with registration and investment, and leaves userRewardInfo(helper) equal to (100e18, 100e18, 300e18, 0, 0, 0, 0, 0, 0, 0). That is the prerequisite that makes later pair buys succeed.
The victim storage snapshot also fixes the main protocol addresses used by the exploit:
slot 1: YYSCoin 0xe814cc2b4dbfe652c04f2e008ced18875c76f510
slot 2: USDT 0x55d398326f99059ff775485246999027b3197955
slot 4: router 0x8228a4ad192d5d82189afd6e194f65edb8c76a41
slot 5: pair 0x4200a9b80b1e84cf94ad8fc28f66195bc3c37f3f
Those addresses match the exploit trace, where the victim contract removes liquidity from the YYSCoin/USDT pair and directs the output to the attacker-controlled helper.
This incident is an ATTACK-class ACT vulnerability in the YYSCoin reward contract. The safety invariant is straightforward: LP tokens held by the victim contract represent protocol-owned liquidity and must not be redeemable by an arbitrary external caller unless redemption is tied to the caller's own LP entitlement or an explicit authorization check. The collected evidence shows that sell(uint256) does not enforce that invariant.
The exploit path is permissionless end to end. A fresh attacker can deploy a helper contract, call the public registration flow with 100 USDT to obtain positive qq, acquire YYSCoin from the public pair, and then call sell(uint256) with attacker-supplied YYSCoin amounts. Once inside sell(uint256), the victim contract uses its own LP balance, already approved to the router, to execute removeLiquidity(USDT, YYSCoin, ..., msg.sender, block.timestamp). The router then burns LP from the pair and transfers the underlying USDT and YYSCoin to the attacker helper rather than back to the victim.
The first sell call alone nearly empties the victim's LP position. The balance diff shows victim LP dropping by 137403151576350329973505, and the trace shows the first sell(38584476947058482497324) triggering removeLiquidity(..., 136390063935146319461909, ..., attacker, ...). Later sell calls continue redeeming the remaining victim-held LP until only 364589772282315947621 LP tokens remain. The flash lender 0x92b7807bf19b7dddf89b706143896d05228f3121 is repaid with the required fee, proving the unauthorized LP redemption itself is what funds the attacker's profit.
The attacker sequence starts from BSC pre-state immediately before block 39436649. At that point, all relevant contracts, balances, router and pair addresses, and the victim-held LP balance are publicly readable from chain state. No private key compromise, privileged role, or attacker-only bytecode is required for exploitability.
The first adversary-crafted transaction, 0x9423d3d1f15a9cdd51e3a3b452249cb22516157efead1acc44aabb06a1873bf8, deploys helper contract 0x832e6540da54d07cb0dfea8957be690c8eb2c6a0. The second, 0x42d9e7fb1a8afd861abae4af058295c45b22f307bd0165135a74e9faf96b162a, calls that helper with 0.2 BNB and executes the public registration path. The replay notes show the helper depositing WBNB, swapping into USDT, approving the victim, and invoking selector 0xb9b8c246, which the evidence identifies as invest(address,uint256). After that step, userRewardInfo(helper).qq is positive, satisfying the YYSCoin transfer gate for pair buys.
The third transaction, 0xfda026b479c5e0070f4eed542b292031f4e077c6917d211820c572ac33842cda, deploys implementation contract 0x4192abd1466b49be9d1e99918aee99e0dbd65289, which the helper later delegatecalls during the exploit. The final transaction, 0x397a09af6494c0bfcd89e010f5dd65d90f3ee1cf1ff813ce5b0c1d42a1c8dec9, is the actual drain. In the collected trace, the helper borrows 4750000000000000000000000 raw USDT units from flash pool 0x92b7807bf19b7dddf89b706143896d05228f3121, buys YYSCoin from the public pair, and then repeatedly calls the victim's sell(uint256).
The breakpoint is visible in the trace itself:
0xcC0F...::sell(38584476947058482497324)
PancakeRouter::removeLiquidity(USDT, YYSCoin, 136390063935146319461909, 0, 0, 0x832E..., 1717861498)
PancakePair::burn(0x832E...)
That flow proves the victim contract is redeeming LP that it owns and routing the output to the attacker helper 0x832e.... The balance diff independently confirms the effect. Victim LP at pair 0x4200a9b80b1e84cf94ad8fc28f66195bc3c37f3f falls from 137767741348632645921126 to 364589772282315947621, pair USDT falls by 29362002659163955645646, flash pool USDT increases by 475000000000000000000, and attacker EOA 0x101723... gains 28942729962589664590904 raw USDT units.
The YYSCoin source explains why registration is a real prerequisite but not a security boundary. On pair-to-user transfers, the token requires:
if (from == innerPair) {
(, uint256 qq,,,,,,,,) = ddd.userRewardInfo(to);
require(qq > 0, "b");
}
The setup replay proves that qq > 0 can be obtained through the public 100-USDT registration flow. Once that single public gate is cleared, nothing in the victim's sell path binds LP redemption to a caller-owned LP position, which is why arbitrary registered users can drain protocol-held liquidity.
The adversary used four attacker-crafted transactions on BSC:
1. 0x9423d3d1f15a9cdd51e3a3b452249cb22516157efead1acc44aabb06a1873bf8 deploy helper
2. 0x42d9e7fb1a8afd861abae4af058295c45b22f307bd0165135a74e9faf96b162a public registration
3. 0xfda026b479c5e0070f4eed542b292031f4e077c6917d211820c572ac33842cda deploy implementation
4. 0x397a09af6494c0bfcd89e010f5dd65d90f3ee1cf1ff813ce5b0c1d42a1c8dec9 flash-loan drain
In stage 1, the EOA creates helper 0x832e... with references to USDT, the flash pool, the victim contract, and Pancake router infrastructure. In stage 2, the EOA funds the helper with 0.2 BNB so it can buy the 100 USDT needed for registration. That gives the helper positive qq, which is the exact capability needed to receive YYSCoin from the pair.
In stage 3, the EOA deploys implementation 0x4192..., which the helper later delegatecalls during the exploit transaction. In stage 4, the helper borrows from the public flash pool, buys YYSCoin, calls victim sell(uint256) eleven times, swaps residual YYSCoin back into USDT, repays FLASH_AMOUNT + fee, and forwards the remaining profit to the EOA. The attacker-related accounts identified in the analysis are consistent with this flow: the EOA is the sender and final profit recipient, the helper is the on-chain execution vehicle, and the implementation is the code delegated into during the drain.
The measurable impact is a direct depletion of the YYSCoin/USDT liquidity that was represented by LP held in the victim reward contract. The pair loses 29362002659163955645646 raw USDT units in the exploit transaction, and the victim reward contract's LP balance is reduced by 137403151576350329973505 LP tokens, leaving only 364589772282315947621 LP tokens.
The attacker realizes 28942729962589664590904 raw USDT units after repaying the flash fee. Native gas cost to the EOA is 3381459000000000 wei. The public profit predicate is therefore satisfied entirely through permissionless on-chain actions using public state, public token markets, and a public flash primitive.
0x397a09af6494c0bfcd89e010f5dd65d90f3ee1cf1ff813ce5b0c1d42a1c8dec9sell(uint256), router removeLiquidity, and pair burn0xb9b8c246userRewardInfo(to).qq > 039436649 to 39436765qq