FlashLoanExecutor

Description:

Decentralized Finance (DeFi) protocol contract providing Swap, Factory functionality.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/FlashLoanExecutor.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/// @notice Minimal ERC20 interface
interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function approve(address spender, uint256 amount) external returns (bool);
}

/// @notice Aave v3 lending pool interface (flashLoanSimple)
interface IAavePool {
    function flashLoanSimple(
        address receiver,
        address asset,
        uint256 amount,
        bytes calldata params,
        uint16 referralCode
    ) external;
}

/// @notice Balancer vault interface (single-token flash loan)
interface IBalancerVault {
    function flashLoan(
        address recipient,
        address[] calldata tokens,
        uint256[] calldata amounts,
        bytes calldata userData
    ) external;
}

interface IBalancerFlashLoanRecipient {
    function receiveFlashLoan(
        address[] calldata tokens,
        uint256[] calldata amounts,
        uint256[] calldata feeAmounts,
        bytes calldata userData
    ) external;
}

/// @notice Uniswap v3 pool interface (flash)
interface IUniswapV3Pool {
    function flash(
        address recipient,
        uint256 amount0,
        uint256 amount1,
        bytes calldata data
    ) external;

    function token0() external view returns (address);
    function token1() external view returns (address);
}

interface IUniswapV3FlashCallback {
    function uniswapV3FlashCallback(
        uint256 fee0,
        uint256 fee1,
        bytes calldata data
    ) external;
}

/// @notice Lightweight ownable helper
abstract contract Ownable {
    address public owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor(address initialOwner) {
        require(initialOwner != address(0), "EXECUTOR:ZERO_OWNER");
        owner = initialOwner;
        emit OwnershipTransferred(address(0), initialOwner);
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "EXECUTOR:NOT_OWNER");
        _;
    }

    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "EXECUTOR:ZERO_OWNER");
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}

/// @notice Flash loan executor that routes between multiple providers
contract FlashLoanExecutor is Ownable, IBalancerFlashLoanRecipient, IUniswapV3FlashCallback {
    struct SwapPayload {
        address buyTarget;
        bytes buyData;
        uint256 buyValue;
        address sellTarget;
        bytes sellData;
        uint256 sellValue;
    }

    struct ProviderConfig {
        bool enabled;
        address target;
        bytes providerData;
        uint16 assumedFeeBps; // informational
    }

    struct FlashContext {
        bool active;
        uint8 providerId;
        address asset;
        uint256 amount;
        SwapPayload payload;
        address initiator;
    }

    mapping(uint8 => ProviderConfig) public providers;
    FlashContext private _ctx;

    event ProviderConfigured(uint8 indexed providerId, address target, bool enabled);

    error UnknownProvider(uint8 providerId);
    error ProviderDisabled(uint8 providerId);
    error InvalidCaller(uint8 providerId);
    error InFlightFlashLoan();

    constructor(address initialOwner) Ownable(initialOwner) {}

    // ---------------------------------------------------------------------
    // Provider configuration
    // ---------------------------------------------------------------------

    function setProvider(
        uint8 providerId,
        bool enabled,
        address target,
        bytes calldata providerData,
        uint16 assumedFeeBps
    ) external onlyOwner {
        providers[providerId] = ProviderConfig({
            enabled: enabled,
            target: target,
            providerData: providerData,
            assumedFeeBps: assumedFeeBps
        });
        emit ProviderConfigured(providerId, target, enabled);
    }

    function getContext() external view returns (FlashContext memory) {
        return _ctx;
    }

    // ---------------------------------------------------------------------
    // Entry point invoked off-chain via bundle builder
    // ---------------------------------------------------------------------

    function executeFlashArb(
        uint8 providerId,
        address asset,
        uint256 amount,
        bytes calldata swapPayload
    ) external onlyOwner {
        ProviderConfig memory config = providers[providerId];
        if (!config.enabled) revert ProviderDisabled(providerId);
        if (_ctx.active) revert InFlightFlashLoan();

        SwapPayload memory payload = abi.decode(swapPayload, (SwapPayload));

        _ctx = FlashContext({
            active: true,
            providerId: providerId,
            asset: asset,
            amount: amount,
            payload: payload,
            initiator: msg.sender
        });

        if (providerId == 1) {
            _executeAave(config, asset, amount, payload);
        } else if (providerId == 2) {
            _executeBalancer(config, asset, amount);
        } else if (providerId == 3) {
            _executeUniswap(config, asset, amount);
        } else {
            _ctx.active = false;
            revert UnknownProvider(providerId);
        }

        _ctx.active = false;
    }

    // ---------------------------------------------------------------------
    // Provider-specific implementations
    // ---------------------------------------------------------------------

    function _executeAave(
        ProviderConfig memory config,
        address asset,
        uint256 amount,
        SwapPayload memory payload
    ) internal {
        address pool = config.target;
        require(pool != address(0), "EXECUTOR:AAVE_TARGET");
        bytes memory params = abi.encode(payload);
        IAavePool(pool).flashLoanSimple(address(this), asset, amount, params, 0);
    }

    function executeOperation(
        address asset,
        uint256 amount,
        uint256 premium,
        address initiator,
        bytes calldata params
    ) external returns (bool) {
        require(_ctx.active && _ctx.providerId == 1, "EXECUTOR:AAVE_STATE");
        require(initiator == address(this), "EXECUTOR:AAVE_INITIATOR");
        require(msg.sender == providers[1].target, "EXECUTOR:AAVE_CALLER");

        SwapPayload memory payload = abi.decode(params, (SwapPayload));
        _performSwaps(payload);

        _repay(asset, msg.sender, amount + premium);
        return true;
    }

    function _executeBalancer(
        ProviderConfig memory config,
        address asset,
        uint256 amount
    ) internal {
        address vault = config.target;
        require(vault != address(0), "EXECUTOR:BAL_TARGET");
        address[] memory tokens = new address[](1);
        tokens[0] = asset;
        uint256[] memory amounts = new uint256[](1);
        amounts[0] = amount;
        IBalancerVault(vault).flashLoan(address(this), tokens, amounts, "");
    }

    function receiveFlashLoan(
        address[] calldata tokens,
        uint256[] calldata amounts,
        uint256[] calldata feeAmounts,
        bytes calldata /*userData*/
    ) external override {
        require(_ctx.active && _ctx.providerId == 2, "EXECUTOR:BAL_STATE");
        require(msg.sender == providers[2].target, "EXECUTOR:BAL_CALLER");

        _performSwaps(_ctx.payload);

        _repay(tokens[0], msg.sender, amounts[0] + feeAmounts[0]);
    }

    function _executeUniswap(
        ProviderConfig memory config,
        address asset,
        uint256 amount
    ) internal {
        (address pool, bool borrowToken0) = abi.decode(config.providerData, (address, bool));
        require(pool != address(0), "EXECUTOR:UNI_POOL");

        if (borrowToken0) {
            require(IUniswapV3Pool(pool).token0() == asset, "EXECUTOR:UNI_TOKEN0");
            IUniswapV3Pool(pool).flash(address(this), amount, 0, abi.encode(asset));
        } else {
            require(IUniswapV3Pool(pool).token1() == asset, "EXECUTOR:UNI_TOKEN1");
            IUniswapV3Pool(pool).flash(address(this), 0, amount, abi.encode(asset));
        }
    }

    function uniswapV3FlashCallback(
        uint256 fee0,
        uint256 fee1,
        bytes calldata data
    ) external override {
        require(_ctx.active && _ctx.providerId == 3, "EXECUTOR:UNI_STATE");
        require(msg.sender == providers[3].target, "EXECUTOR:UNI_CALLER");

        address asset = abi.decode(data, (address));
        _performSwaps(_ctx.payload);

        uint256 repayAmount = _ctx.amount + (fee0 > 0 ? fee0 : fee1);
        _repay(asset, msg.sender, repayAmount);
    }

    // ---------------------------------------------------------------------
    // Internal helpers
    // ---------------------------------------------------------------------

    function _performSwaps(SwapPayload memory payload) internal {
        if (payload.buyData.length > 0) {
            (bool success, bytes memory returndata) = payload.buyTarget.call{value: payload.buyValue}(payload.buyData);
            require(success, string(returndata.length > 0 ? returndata : bytes("EXECUTOR:BUY_FAIL")));
        }

        if (payload.sellData.length > 0) {
            (bool success, bytes memory returndata) = payload.sellTarget.call{value: payload.sellValue}(payload.sellData);
            require(success, string(returndata.length > 0 ? returndata : bytes("EXECUTOR:SELL_FAIL")));
        }
    }

    function _repay(address token, address target, uint256 amount) internal {
        require(IERC20(token).transfer(target, amount), "EXECUTOR:REPAY" );
    }

    // Allow owner to recover tokens/ETH accidentally left in the contract
    function sweep(address token, address to) external onlyOwner {
        if (token == address(0)) {
            (bool ok, ) = to.call{value: address(this).balance}('');
            require(ok, "EXECUTOR:SWEEP_ETH");
        } else {
            uint256 bal = IERC20(token).balanceOf(address(this));
            require(IERC20(token).transfer(to, bal), "EXECUTOR:SWEEP_TOKEN");
        }
    }

    receive() external payable {}
}
"
    }
  },
  "settings": {
    "evmVersion": "paris",
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    }
  }
}}

Tags:
DeFi, Swap, Factory|addr:0xd25730ea7d522095312234de25e6fd0ba62f1dc4|verified:true|block:23564031|tx:0xd873fb3f345803aa820d751b2ce0447d1948316c31f88830ef92bf749d80010d|first_check:1760340638

Submitted on: 2025-10-13 09:30:38

Comments

Log in to comment.

No comments yet.