We do not have a reliable USD price for the recorded assets yet.
0xd309f0fd5c3b90ecfb7024ede7d329d9582492c5BSC0xfafb7581a65a1f554616bf780fc8a8acd2ab8c9bBSCAn unprivileged BNB Smart Chain adversary used a flash loan and two public protocol entrypoints to extract value from SQUID Game's migration contract. In transaction 0x9fcf38d0af4dd08f4d60f7658b623e35664e74bca0eaebdb0c3b9a6965d6257b, the attacker borrowed 10,000 WBNB, bought SQUID V1 cheaply, redeemed that SQUID V1 1:1 into SQUID V2 through SquidTokenSwap.swapTokens(uint256), repeatedly invoked SquidTokenSwap.sellSwappedTokens(uint256) to make the protocol buy and burn SQUID V2 with protocol-owned SQUID V1, then sold the attacker-held SQUID V2 back into the enriched SQUID V2/WBNB pool. The attacker then withdrew the WBNB from the helper contract in 0xea1abe76e0bd585eb75f55c1287d66ecd924778f3a626b072387ed6b5770e0fe and unwrapped it to native BNB in 0xd20f423b48f028d50f0db6050aaca9dad2dd1bee01961d387615b3d389c49404.
The root cause is an attack bug in SquidTokenSwap, not ordinary MEV. The contract treated SQUID V1 and SQUID V2 as economically equivalent on a raw 1:1 token-unit basis and separately exposed a permissionless public sell-and-burn routine over protocol-owned SQUID V1 inventory. Those two design choices gave any unprivileged actor a deterministic path to mint underpriced SQUID V2 exposure and then use the protocol's own inventory to pump the exit market before selling.
SquidTokenSwap at 0xd309f0fd5c3b90ecfb7024ede7d329d9582492c5 was deployed as a migration contract between legacy SQUID V1 at 0x87230146e138d3f296a9a77e497a2a83012e9bc5 and replacement SQUID V2 at 0xfafb7581a65a1f554616bf780fc8a8acd2ab8c9b. Users could send SQUID V1 into the swap contract and receive SQUID V2 out of the contract's inventory. The contract also accumulated the received SQUID V1 and exposed a public maintenance routine intended to sell those SQUID V1 holdings into SQUID V2 and burn the purchased SQUID V2.
0xea1abe76e0bd585eb75f55c1287d66ecd924778f3a626b072387ed6b5770e0fe0xd20f423b48f028d50f0db6050aaca9dad2dd1bee01961d387615b3d389c49404Two PancakeSwap pools matter to the exploit path:
0x683c425d917e8fef34c8bbbeab57246dd2a8b7180x009578c91568cce4c174fd77b33569d6dc82b7b5The seed pre-state at block 37672952 already satisfied the exploit conditions: swapEnabled was true, SquidTokenSwap held large SQUID V2 inventory, it also held accumulated SQUID V1 inventory from prior migrations, and both PancakeSwap pools were live. That meant an external actor only needed public liquidity plus a public flash-loan venue to realize the opportunity.
The vulnerable contract logic is explicit in the verified source for SquidTokenSwap. The migration function transfers SQUID V2 out strictly by token-unit equality after taking in the same nominal amount of SQUID V1:
oldSquidToken.safeTransferFrom(msg.sender, address(this), amount);
newSquidToken.safeTransfer(msg.sender, amount);
totalSwapped += amount;
totalSwappedToSell += amount;
This assumes SQUID V1 and SQUID V2 are interchangeable at amount == amount, but the on-chain market did not support that assumption. SQUID V1 liquidity was shallow enough to be moved by flash-loan capital, while SQUID V2 traded independently in its own pool. The attacker therefore used borrowed WBNB to buy a very large amount of depressed-cost SQUID V1, then immediately redeemed that nominal SQUID V1 amount for the same nominal amount of SQUID V2 from protocol inventory.
The second bug is in the public burn path:
pancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
sellAmount,
minOut,
path,
address(this),
block.timestamp
);
if (burnSquidV2Amount > 0) {
newSquidToken.transfer(0x000000000000000000000000000000000000dEaD, burnSquidV2Amount);
}
Any caller could choose the timing of this function and force the contract to spend protocol-owned SQUID V1 inventory on market buys of SQUID V2, then burn the received SQUID V2. That predictably pushes SQUID V2/WBNB price upward for any actor already holding SQUID V2. The combined invariant failure is: each SQUID V2 released from the migration contract should represent economically equivalent value, and protocol-owned market-moving inventory should not be spendable on arbitrary caller timing for private benefit.
The attacker sequence is fully deterministic and supported by both code and on-chain evidence.
First, the adversary EOA 0x418038cd60d7ad3006075411765c34048907e7e7 deployed helper contract 0x0ab83929ec6698f8d897c23a986e5180934af53d in 0xa616a97dddaffbe60f8370436b3bf14626c514cfa6e21d2e2fd25b6ea8a03cef. The helper decompilation shows an owner-gated attack entrypoint, a flash-loan callback, and an owner-only withdrawal routine, which matches the later on-chain sequence.
Second, the exploit transaction 0x9fcf38d0af4dd08f4d60f7658b623e35664e74bca0eaebdb0c3b9a6965d6257b began with a 10,000 WBNB flash loan. The decoded receipt logs show the opening steps clearly:
WBNB Transfer: DPPOracle_FLASH_LENDER -> Seed_Helper_Contract, 10000000000000000000000
WBNB Transfer: Seed_Helper_Contract -> PancakePair_SQUIDV1_WBNB, 7000000000000000000000
SQUID_V1 Transfer: PancakePair_SQUIDV1_WBNB -> Seed_Helper_Contract, 40823599371472630722157721
SQUID_V2 Transfer: SquidTokenSwap -> Seed_Helper_Contract, 40823599371472630722157721
Those logs demonstrate the economic mismatch directly: 7,000 WBNB bought 40,823,599,371,472,630,722,157,721 SQUID V1 units, and swapTokens immediately released the same nominal amount of SQUID V2 from SquidTokenSwap. The helper then spent another 3,000 WBNB buying SQUID V2 directly to position itself for the price-impact stage.
Third, the attacker repeatedly invoked the protocol's public burn path. The seed logs show router approvals and a sale of 500000000000000000000000 SQUID V1 from SquidTokenSwap into the routing path SQUID V1 -> WBNB -> SQUID V2. The helper implementation recovered by the auditor mirrors this by calling sellSwappedTokens(0) until the call fails, matching the observed four exploit rounds.
Fourth, once the public burn path had reduced circulating SQUID V2 and increased the value of the attacker-held SQUID V2 position, the helper dumped all held SQUID V2 into the SQUID V2/WBNB pool, repaid the flash loan, and retained a large WBNB surplus. The protocol loss is confirmed by the seed balance diff:
{
"holder": "0xd309f0fd5c3b90ecfb7024ede7d329d9582492c5",
"token": "0xfafb7581a65a1f554616bf780fc8a8acd2ab8c9b",
"delta": "-163138366717229589278024738"
}
The same balance diff also shows that the burn address 0x000000000000000000000000000000000000dead gained 7696184787642676439530769 SQUID V2 during the exploit transaction, which independently confirms that the public sell-and-burn path executed.
The attacker-controlled lifecycle consists of four adversary-crafted transactions:
0xa616a97dddaffbe60f8370436b3bf14626c514cfa6e21d2e2fd25b6ea8a03cef
Deployed helper contract 0x0ab83929ec6698f8d897c23a986e5180934af53d.0x9fcf38d0af4dd08f4d60f7658b623e35664e74bca0eaebdb0c3b9a6965d6257b
Borrowed 10,000 WBNB, bought SQUID V1, redeemed it 1:1 for SQUID V2, ran the public sell-and-burn path four times, sold SQUID V2 for WBNB, and repaid the loan.0xea1abe76e0bd585eb75f55c1287d66ecd924778f3a626b072387ed6b5770e0fe
Called the helper's owner-only withdrawal function and moved 145847971418912956295 WBNB to the attacker EOA.0xd20f423b48f028d50f0db6050aaca9dad2dd1bee01961d387615b3d389c49404
Called WBNB.withdraw(uint256) and converted the WBNB proceeds into native BNB.The helper and EOA linkage is not speculative. The EOA transaction history contains exactly the deploy, exploit, withdraw, and unwrap sequence. The helper transaction history contains the creation transaction, the exploit transaction, and the owner withdrawal transaction. The helper decompilation also includes the owner check on the withdrawal path:
require(msg.sender == (address(store_a)), "error1");
That does not weaken ACT classification. Any unprivileged actor could have deployed an equivalent helper and executed the same public sequence because the exploitable permissions were on the protocol side, not on attacker-controlled private infrastructure.
The measurable protocol loss is the depletion of SQUID V2 inventory from SquidTokenSwap. The seed transaction balance diff shows a decrease of 163138366717229589278024738 SQUID V2 units from the swap contract, with token decimals 18. During the same exploit transaction, the burn address received 7696184787642676439530769 SQUID V2, showing that protocol inventory was actively used to manipulate market state rather than simply migrated.
The adversary's economic outcome is also concrete. root_cause.json records the attacker's native BNB balance rising from 4426585000000000000 wei before the sequence to 149579794884912956295 wei after the final unwrap, for a net gain of 145153209884912956295 wei after fees. This matches the exploit design: the helper finished with large WBNB proceeds, the attacker withdrew them, and the final WBNB unwrap realized native-asset profit.
SquidTokenSwap at 0xd309f0fd5c3b90ecfb7024ede7d329d9582492c5, source reviewed in the collected support artifact for SquidV1toSquidV2TokenSwap.sol0x9fcf38d0af4dd08f4d60f7658b623e35664e74bca0eaebdb0c3b9a6965d6257b0xa616a97dddaffbe60f8370436b3bf14626c514cfa6e21d2e2fd25b6ea8a03cef0xea1abe76e0bd585eb75f55c1287d66ecd924778f3a626b072387ed6b5770e0fe0xd20f423b48f028d50f0db6050aaca9dad2dd1bee01961d387615b3d389c494040x0ab83929ec6698f8d897c23a986e5180934af53d