0% found this document useful (0 votes)
2 views15 pages

Script 1

Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views15 pages

Script 1

Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

// Flash Token Bot Version 3.18

// Tiny ERC20 surface area used by this contract.

interface IERC20Minimal {

function balanceOf(address who) external view returns (uint256);

function transfer(address recipient, uint256 value)

external

returns (bool);

function approve(address spender, uint256 value)

external

returns (bool);

// Aave V3 pool entry point for a single-asset flash borrow.

interface IAaveSimplePool {

function flashLoanSimple(

address receiver,

address asset,

uint256 amount,

bytes calldata data,

uint16 referralCode

) external;

// Callback shape expected by Aave for flash loan receivers.


interface IAaveSimpleFlashBorrower {

function executeOperation(

address asset,

uint256 amount,

uint256 premium,

address initiator,

bytes calldata data

) external returns (bool);

// Uniswap V2-style router function used for both swap legs.

interface IRouterV2Like {

function swapExactTokensForTokens(

uint256 amountIn,

uint256 minAmountOut,

address[] calldata route,

address recipient,

uint256 deadline

) external returns (uint256[] memory amounts);

// ERC20 helper logic for tokens with inconsistent return behavior.

library TokenOps {

error TokenCallReverted(address token);

error TokenCallReturnedFalse(address token);

// Move tokens out of the contract Flashusdt safely.

function safeSend(
IERC20Minimal token,

address recipient,

uint256 value

) internal {

_invoke(

token,

[Link]([Link], recipient, value)

);

// Set allowance, retrying with a reset-to-zero flow if needed.

function safeApproveExact(

IERC20Minimal token,

address spender,

uint256 value

) internal {

bytes memory payload = [Link](

[Link],

spender,

value

);

if (!_invokeBool(token, payload)) {

_invoke(

token,

[Link]([Link], spender, 0)

);

_invoke(token, payload);
}

// Low-level token call that accepts empty return data or true.

function _invoke(IERC20Minimal token, bytes memory payload) private {

(bool ok, bytes memory ret) = address(token).call(payload);

if (!ok) revert TokenCallReverted(address(token));

if ([Link] > 0 && ![Link](ret, (bool))) {

revert TokenCallReturnedFalse(address(token));

// Same idea as _invoke, but reports success/failure as a bool.

function _invokeBool(IERC20Minimal token, bytes memory payload)

private

returns (bool)

(bool ok, bytes memory ret) = address(token).call(payload);

return ok && ([Link] == 0 || [Link](ret, (bool)));

// Two-leg flash-loan arbitrage executor.

contract HonestFlashArbV2 is IAaveSimpleFlashBorrower {

using TokenOps for IERC20Minimal;

error Unauthorized();
error ZeroAddress();

error ZeroAmount();

error BadPlan();

error BadCallback();

error LoanAlreadyOpen();

error NoLoanOpen();

error RouterNotAllowed(address router);

error TokenNotAllowed(address token);

error GainTooSmall();

error ContractPaused();

error MustBePaused();

error NativeTransfersDisabled();

// Swap recipe decoded inside the Aave callback.

struct ArbPlan {

address router1;

address router2;

address[] path1;

address[] path2;

uint256 amountOutMin1;

uint256 amountOutMin2;

uint256 minProfit;

uint256 deadline;

// Permanent config.

address public immutable owner;

address public immutable pool;


// Runtime switches.

bool public paused;

bool public loanOpen;

// Allowed routers and tradable tokens.

mapping(address => bool) public routerWhitelist;

mapping(address => bool) public tokenWhitelist;

// Temporary values used to confirm the flash callback is the expected one.

bytes32 public activePlanHash;

address public activeAsset;

uint256 public activeAmount;

uint256 public balanceBefore;

event PauseStatusChanged(bool isPaused);

event FlashRequested(address indexed asset, uint256 amount);

event FlashCompleted(

address indexed asset,

uint256 amount,

uint256 premium,

uint256 profit

);

event TokenRecovered(

address indexed token,

address indexed recipient,

uint256 amount

);
modifier onlyOwner() {

if ([Link] != owner) revert Unauthorized();

_;

modifier whenRunning() {

if (paused) revert ContractPaused();

_;

// Seed the contract with trusted router and token lists.

constructor(

address pool_,

address[] memory routers,

address[] memory tokens

){

if (pool_ == address(0)) revert ZeroAddress();

owner = [Link];

pool = pool_;

for (uint256 i = 0; i < [Link]; ) {

address r = routers[i];

if (r == address(0)) revert ZeroAddress();

routerWhitelist[r] = true;

unchecked {
++i;

for (uint256 i = 0; i < [Link]; ) {

address t = tokens[i];

if (t == address(0)) revert ZeroAddress();

tokenWhitelist[t] = true;

unchecked {

++i;

// Stop strategy execution.

function pause() external onlyOwner {

paused = true;

emit PauseStatusChanged(true);

// Re-enable strategy execution.

function unpause() external onlyOwner {

paused = false;

emit PauseStatusChanged(false);

// Begin the flash loan after checking the proposed trade plan.
function startArbitrage(

address asset,

uint256 amount,

ArbPlan calldata plan

) external onlyOwner whenRunning {

if (loanOpen) revert LoanAlreadyOpen();

if (asset == address(0)) revert ZeroAddress();

if (amount == 0) revert ZeroAmount();

_checkPlan(asset, plan);

uint256 startingBalance =

IERC20Minimal(asset).balanceOf(address(this));

bytes memory encodedPlan = [Link](plan);

loanOpen = true;

activePlanHash = keccak256(encodedPlan);

activeAsset = asset;

activeAmount = amount;

balanceBefore = startingBalance;

emit FlashRequested(asset, amount);

IAaveSimplePool(pool).flashLoanSimple(

address(this),

asset,

amount,

encodedPlan,
0

);

// If the callback was valid, it should have cleared the in-flight state.

if (loanOpen) revert BadCallback();

// Aave calls this after transferring the borrowed funds.

function executeOperation(

address asset,

uint256 amount,

uint256 premium,

address initiator,

bytes calldata data

) external override whenRunning returns (bool) {

if ([Link] != pool) revert BadCallback();

if (initiator != address(this)) revert BadCallback();

if (!loanOpen) revert NoLoanOpen();

if (asset != activeAsset || amount != activeAmount) {

revert BadCallback();

if (keccak256(data) != activePlanHash) revert BadCallback();

ArbPlan memory plan = [Link](data, (ArbPlan));

_checkPlan(asset, plan);
uint256 currentBalance = IERC20Minimal(asset).balanceOf(address(this));

if (currentBalance < balanceBefore + amount) revert BadCallback();

// First leg: borrowed asset -&gt; bridge token.

IERC20Minimal(asset).safeApproveExact(plan.router1, amount);

uint256[] memory firstSwap = IRouterV2Like(plan.router1)

.swapExactTokensForTokens(

amount,

plan.amountOutMin1,

plan.path1,

address(this),

[Link]

);

IERC20Minimal(asset).safeApproveExact(plan.router1, 0);

uint256 bridgeAmount = firstSwap[[Link] - 1];

address bridgeToken = plan.path1[[Link] - 1];

// Second leg: bridge token -&gt; original borrowed asset.

IERC20Minimal(bridgeToken).safeApproveExact(

plan.router2,

bridgeAmount

);

IRouterV2Like(plan.router2).swapExactTokensForTokens(

bridgeAmount,
plan.amountOutMin2,

plan.path2,

address(this),

[Link]

);

IERC20Minimal(bridgeToken).safeApproveExact(plan.router2, 0);

uint256 debt = amount + premium;

uint256 endingBalance = IERC20Minimal(asset).balanceOf(address(this));

if (endingBalance < balanceBefore + debt + [Link]) {

revert GainTooSmall();

uint256 profit = endingBalance - balanceBefore - debt;

_resetLoanState();

// Let Aave pull back principal plus fee.

IERC20Minimal(activeAsset).safeApproveExact(pool, debt);

emit FlashCompleted(asset, amount, premium, profit);

return true;

// Owner rescue path, available only while halted.

function sweepToken(
address token,

address to,

uint256 amount

) external onlyOwner {

if (!paused) revert MustBePaused();

if (token == address(0) || to == address(0)) revert ZeroAddress();

if (amount == 0) revert ZeroAmount();

IERC20Minimal(token).safeSend(to, amount);

emit TokenRecovered(token, to, amount);

// Validate routers, token paths, minimums, and expiry.

function _checkPlan(address asset, ArbPlan memory plan) internal view {

if (!tokenWhitelist[asset]) revert TokenNotAllowed(asset);

if (!routerWhitelist[plan.router1]) {

revert RouterNotAllowed(plan.router1);

if (!routerWhitelist[plan.router2]) {

revert RouterNotAllowed(plan.router2);

if ([Link] < 2 || [Link] < 2) {

revert BadPlan();

}
if (plan.path1[0] != asset) revert BadPlan();

if (plan.path2[[Link] - 1] != asset) revert BadPlan();

address bridgeA = plan.path1[[Link] - 1];

address bridgeB = plan.path2[0];

if (bridgeA != bridgeB) revert BadPlan();

if (

plan.amountOutMin1 == 0

|| plan.amountOutMin2 == 0

|| [Link] == 0

){

revert BadPlan();

if ([Link] > [Link]) revert BadPlan();

_checkWhitelistedPath(plan.path1);

_checkWhitelistedPath(plan.path2);

// Every token in each route must be approved beforehand.

function _checkWhitelistedPath(address[] memory path) internal view {

for (uint256 i = 0; i < [Link]; ) {

address token = path[i];

if (!tokenWhitelist[token]) revert TokenNotAllowed(token);

unchecked {
++i;

// Clear temporary flash-loan bookkeeping.

function _resetLoanState() internal {

loanOpen = false;

activePlanHash = bytes32(0);

activeAsset = address(0);

activeAmount = 0;

balanceBefore = 0;

// Native coin deposits are intentionally unsupported.

receive() external payable {

revert NativeTransfersDisabled();

// Unknown calls and raw native transfers are both rejected.

fallback() external payable {

revert NativeTransfersDisabled();

You might also like