Kapatmak için ESC'ye basın

MEV Bot Karlılığı ve Gaz Ücretleri: Arbitraj Rehberi

MEV'in saf ekonomisi, milisaniyelik ağ gecikmelerinin tüm potansiyel kârı yok ettiği, işlem blokları için verilen acımasız bir rekabete dayanır. Ethereum veya Layer 2 EVM ağlarında kendi botunuzu çalıştırmak çoktan kolay para kazanma dönemi olmaktan çıktı. Piyasa; Frankfurt ve Tokyo'daki veri merkezlerinde, doğrudan validatör node'larının yanında sunucu kiralayan özel arama (searcher) firmaları tarafından paylaşılmış durumda.

Gerçek Rakamlar ve Kârlılık

Ev sunucusundan veya standart bir bulut VPS'ten çalıştırılan tekil bir bot, gas açık artırmaları yüzünden %95 ihtimalle zararına çalışır. Kârlılık tamamen stratejiye bağlıdır:

  • Atomik Arbitraj (Atomic Arbitrage): İşlem marjları yüzde birin kesirlerine kadar düştü. Başarılı bir botun volatilite dönemlerindeki net günlük kârı 100$ ile 3.000$ arasında değişir. İşlem tek bir atomik akıllı kontrat içine sarıldığı için sermaye kaybetme riski sıfırdır: koşullar uyuşmazsa tüm zincir geri alınır (revert).
  • Sandwich Saldırıları (Sandwich Attacks): Uniswap v2 veya benzeri AMM'lerde düşük likiditeli paritelerde günde 500$ ila 10.000$ arasında değişen teorik getiri daha yüksektir. Ancak işin pratiği çok daha serttir. Rakip botlar, özel işlem havuzları üzerinden sıraya girerek validatörlere başkalarının verdiği rüşvetleri bastırır.
  • Tasfiyeler (Liquidations): Aave gibi borç verme protokollerinin spot piyasası büyük vurgunlar vadeder, ancak borçları kapatmak ve pozisyonları anında tasfiye etmek için milyonlarca dolarlık likidite gerektirir. Tek başınıza takılıyorsanız burada işiniz yok.

Gas Maliyeti Yapısı ve Builder'lar ile Çalışmak

Bir MEV botu çalıştırırken en büyük harcama kalemi başarılı işlemler değil, başarısız denemeler ve öncelikli blok validasyonu açık artırmalarıdır (Gas Priority Auction).

  • Herkese Açık Mempool: İşlemi özel röleleri (relays) atlayarak göndermek doğrudan zarar yazmak demektir. Sıradan bir bot kurbanın işlemini görür, kendi işlemini daha yüksek gas ile yollar ancak rakip botlar özel RPC'ler üzerinden bunu çoktan kapar. Sonuç olarak işleminiz en kötü fiyattan yürütülür veya tamamen revert olur, blokチェーン üzerinde gerçek gas'inizi yakar.
  • Blok Builder'ları ve Flashbots: Modern arbitraj eth_sendBundle üzerinden yürür. Birden fazla işlemden oluşan bir bundle (paket) oluşturup bunu doğrudan validatörlere gönderirsiniz (Beaverbuild, Titan, Flashbots).
  • Başarısızlık Ücreti: Özel bundle'ların avantajı, arbitraj başarısız olduğunda işlemin bloğa hiç girmemesidir. Boşa giden atışlar için ağ komisyonu ödemezsiniz. Dezavantajı ise validatörün kârın aslan payını doğrudan bahşiş olarak (coinbase.transfer) cebine atması ve geliştiriciye brüt kârın %5 ila %15'ini bırakmasıdır.

MEV Stratejileri Metrik Tablosu

StratejiBaşlangıç SermayesiOrtalama Günlük Net KârBaşarı OlasılığıTemel Zarar Nedeni
Atomik Arbitraj5.000$'dan başlayan$50 - $500%15-25Ağ gecikmesinde (latency) rakiplerin gerisinde kalmak
Sandwich Saldırıları20.000$'dan başlayan$200 - $3.000%5-10Validatör açık artırmasında aşırı gas ödemek
Tasfiyeler100.000$ ve üzeri$1.000 - $10.000+< %2Büyük borçları kapatmak için sermaye yetersizliği

Python ile Özel Bundle Gönderimi Örneği

Aşağıda, Flashbots uyumlu bir sağlayıcı üzerinden bundle göndermek için web3.py kütüphanesini kullanan çalışan bir Python betik iskeleti yer almaktadır. Kod gereksiz soyutlamalardan arındırılmıştır.

import os
from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3
from flashbots import flashbot
# Relay isteklerini imzalamak için anahtar (Flashbots itibarı).
# Asla fonlarınızın bulunduğu anahtarı KULLANMAYIN.
signature_account: LocalAccount = Account.from_key(os.environ["FLASHBOTS_SIGNER_KEY"])
# İşlem göndericisinin anahtarı
sender: LocalAccount = Account.from_key(os.environ["SENDER_PRIVATE_KEY"])
w3 = Web3(Web3.HTTPProvider(os.environ["ETH_NODE_URL"]))
flashbot(w3, signature_account, "https://relay-sepolia.flashbots.net")
def build_signed_tx(nonce: int) -> bytes:
    base_fee = w3.eth.get_block("latest")["baseFeePerGas"]
    tx = {
        "to": sender.address,          # örnek: kendine transfer
        "value": 0,
        "gas": 21_000,
        "maxFeePerGas": base_fee * 2 + Web3.to_wei(2, "gwei"),
        "maxPriorityFeePerGas": Web3.to_wei(2, "gwei"),
        "nonce": nonce,
        "chainId": w3.eth.chain_id,
        "type": 2,
    }
    return sender.sign_transaction(tx).rawTransaction  # yeni sürümlerde: .raw_transaction
def send_private_bundle(target_block: int):
    nonce = w3.eth.get_transaction_count(sender.address)
    bundle = [{"signed_transaction": build_signed_tx(nonce)}]
    # Gönderim öncesi simülasyon
    w3.flashbots.simulate(bundle, target_block)
    result = w3.flashbots.send_bundle(bundle, target_block_number=target_block)
    result.wait()  # target_block işlenene kadar bekler
    try:
        return result.receipts()
    except Exception:
        return None  # bundle bloğa dahil edilmedi: sonraki blokta tekrar denenebilir
if __name__ == "__main__":
    target = w3.eth.block_number + 1
    receipts = send_private_bundle(target)
    print("Bloğa dahil edildi" if receipts else "Bundle dahil edilmedi, sonraki blokta tekrar deneyin")

Bundle yalnızca tek bir hedef blok için geçerlidir, bu nedenle pratikte gönderimin ardışık birkaç blok boyunca bir döngü içinde yapılması gerekir. Bloğa girememiş olmak bir hata değildir: rekabet tamamen builder'a verilen bahşişin büyüklüğü üzerinden döner.

Kendi botunuzun kârlılığı doğrudan altyapı maliyetlerine dayanır. Veri merkezinde validatörle aynı kabinde tahsisli sunucu kiralamanın aylık maliyeti 500$'dan başlar. Böyle bir donanımsal hızlandırma olmadan botunuz havuzun durumunu rakiplerinden önce fiziksel olarak hesaplayamaz. Validatöre en kısa kabloyla bağlanan ve spread bulma algoritması en keskin olan kazanır.

Flash loan'lar, büyük sermayelere ihtiyaç duymadan, tek bir işlem (transaction) içerisinde teminatsiz borçlanma yaparak ve zarar durumunda işlemin otomatik olarak iptal edilmesini (rollback) sağlayarak büyük ölçekli arbitraj operasyonları yürütmenize olanak tanır.

Flash Loan'lar ve Akıllı Sözleşme Mimarisi

Arbitraj yapmak için yüz binlerce dolarlık kişisel sermayeye sahip olmak zorunda değilsiniz. Aave v3 veya Balancer havuzlarıyla entegrasyon sözleşmeleri, tek bir işlem sınırı içinde teminatsiz flash loan'lar çekmenize imkan tanır. Bot varlığı ödünç alır, DEX çiftleri üzerinden geçirir, %0.09 komisyonla borcu geri öder ve kalan bakiyeyi oluşturucusunun cüzdanına aktarır. Tüm hesaplamalardan sonra bakiye eksiye düşerse, tüm işlem revert ile iptal edilir ve yayıncı sadece fonksiyon çağrısı için gereken gas ücretini kaybeder.

Solidity ile bir arbitraj sözleşmesi yazmak, EVM bytecode'u için sıkı bir optimizasyon gerektirir. SafeERC20 aracılığıyla standart ERC-20 arayüzlerini kullanmak, işlem sınırlarını kontrol ederken değerli gas birimlerini tüketen fazladan denetimler ekler. Deneyimli geliştiriciler, kalıcı bellek okuma ve yazma işlemlerini (SLOAD/SSTORE) minimumda tutarak call aracılığıyla doğrudan düşük seviyeli (low-level) çağrılar yazarlar.

Solidity Şablon Örneği

Aşağıda, harici kütüphaneler barındırmayan, Uniswap V2 havuzları için Aave V3 flash loan tabanlı bir şablon yer almaktadır:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);
    function approve(address spender, uint256 amount) external returns (bool);
}
/// Aave V3: Tek varlık için flash loan
interface IPool {
    function flashLoanSimple(
        address receiverAddress,
        address asset,
        uint256 amount,
        bytes calldata params,
        uint16 referralCode
    ) external;
}
interface IUniswapV2Pair {
    function token0() external view returns (address);
    function getReserves() external view returns (uint112, uint112, uint32);
    function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;
}
/// Aave V3 flash loan üzerinde arbitraj: asset -> tokenB (pair1) -> asset (pair2).
/// Uniswap V2 tipi havuzlar için örnek. Denetlenmemiştir (Audited değil).
contract FlashArbitrage {
    error Unauthorized();
    error InvalidCaller();
    error InvalidInitiator();
    error TransferFailed();
    error ApproveFailed();
    error InsufficientProfit(uint256 balanceAfter, uint256 required);
    address private immutable OWNER;
    IPool private immutable POOL;
    constructor(address aavePool) {
        OWNER = msg.sender;
        POOL = IPool(aavePool); // Pool adresini ilgili ağın PoolAddressesProvider'ından alın
    }
    modifier onlyOwner() {
        if (msg.sender != OWNER) revert Unauthorized();
        _;
    }
    /// Giriş noktası. `asset` token'ından `amount` kadar borç alır ve executeOperation içinde döngüyü başlatır.
    function executeArbitrage(
        address asset,
        uint256 amount,
        address tokenB,
        address pair1,
        address pair2,
        uint256 minProfit
    ) external onlyOwner {
        bytes memory params = abi.encode(tokenB, pair1, pair2, minProfit);
        POOL.flashLoanSimple(address(this), asset, amount, params, 0);
    }
    /// Aave V3 callback. Kredi verildikten sonra havuz tarafından çağrilir.
    function executeOperation(
        address asset,
        uint256 amount,
        uint256 premium,
        address initiator,
        bytes calldata params
    ) external returns (bool) {
        // 1. Callback'i yalnızca Aave havuzu çağırabilir...
        if (msg.sender != address(POOL)) revert InvalidCaller();
        // 2. ...ve yalnızca bu sözleşmenin kendi isteği üzerine
        if (initiator != address(this)) revert InvalidInitiator();
        (address tokenB, address pair1, address pair2, uint256 minProfit) =
            abi.decode(params, (address, address, address, uint256));
        // Bakiye, alınan fonları halihazırda içermektedir
        uint256 balanceBefore = IERC20(asset).balanceOf(address(this));
        uint256 amountB = _swap(pair1, asset, amount);
        _swap(pair2, tokenB, amountB);
        // Kar = balanceAfter - balanceBefore - premium (kredi komisyonu)
        uint256 balanceAfter = IERC20(asset).balanceOf(address(this));
        uint256 required = balanceBefore + premium + minProfit;
        if (balanceAfter < required) revert InsufficientProfit(balanceAfter, required);
        // Aave borcu transferFrom yoluyla kendi çeker, bu yüzden approve gereklidir
        _safeApprove(asset, address(POOL), amount + premium);
        return true;
    }
    function withdraw(address token, uint256 amount) external onlyOwner {
        _safeTransfer(token, OWNER, amount);
    }
    function _swap(address pair, address tokenIn, uint256 amountIn) private returns (uint256 amountOut) {
        (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pair).getReserves();
        bool zeroForOne = tokenIn == IUniswapV2Pair(pair).token0();
        (uint256 reserveIn, uint256 reserveOut) = zeroForOne ? (r0, r1) : (r1, r0);
        // Uniswap V2 formülü (%0,3 komisyon)
        uint256 amountInWithFee = amountIn * 997;
        amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);
        _safeTransfer(tokenIn, pair, amountIn);
        IUniswapV2Pair(pair).swap(
            zeroForOne ? 0 : amountOut,
            zeroForOne ? amountOut : 0,
            address(this),
            "" // boş data: bu normal bir swap'tir, flash swap değil
        );
    }
    function _safeTransfer(address token, address to, uint256 amount) private {
        if (token.code.length == 0) revert TransferFailed();
        (bool ok, bytes memory data) = token.call(abi.encodeCall(IERC20.transfer, (to, amount)));
        if (!ok || (data.length != 0 && !abi.decode(data, (bool)))) revert TransferFailed();
    }
    function _safeApprove(address token, address spender, uint256 amount) private {
        if (token.code.length == 0) revert ApproveFailed();
        (bool ok, bytes memory data) = token.call(abi.encodeCall(IERC20.approve, (spender, amount)));
        if (!ok || (data.length != 0 && !abi.decode(data, (bool)))) revert ApproveFailed();
    }
}

AWS Altyapı Çıkmazı

Arama botunu Amazon Web Services veya Google Cloud sanal sunucularında barındırmak bütçenizi boşa harcamanın garantisidir. Sanallaştırma, ağ yığınına gecikme (jitter) ekler ve ortak iletişim kanalları, mempool'un yoğun olduğu anlarda paket kaybına (packet loss) uğrar.

Rekabetçi bir kurulum; yüksek tek çekirdekli CPU saat hızına, yerel Geth veya Reth node'u için hızlı NVMe depolamaya ve Frankfurt'taki veri merkezlerine doğrudan gigabit bağlantıya sahip fiziksel bir adanmış sunucu (bare-metal) gerektirir. Kendi hafif (lightweight) node'unuzu çalıştırmak zorunludur; çünkü Infura veya Alchemy gibi halka açık RPC sağlayıcıları, yeni blokların iletim hızını yapay olarak yavaşlatır ve bekleyen (pending) işlem bildirimlerini kritik düzeyde 100-300 milisaniye geciktirir.

MEV'de karı en karmaşık matematiksel modele sahip olan değil, doğrulayıcıya (validator) fiziksel olarak en yakın olan ve bytecode içerisindeki her bir assembly işlemine kadar gas maliyetini hesaplayabilen kazanır.

Bu blog yazısını şununla özetleyin:

FAQ

Tekil bir operatörün atomik arbitraj botu günlük 50 ile 500 dolar arasında net gelir sağlarken, yüksek piyasa oynaklığı dönemlerinde düşük likiditeli havuzlardaki sэндвич saldırıları 200 ile 3.000 dolar arasında kâr getirebilir. Validator düğümleriyle aynı veri merkezinde barındırılmayan standart bulut sunucuları, yüksek ağ gecikmesi ve blok oluşturucu müzayedelerindeki yoğun rekabet yüzünden genellikle zarar eder.

MEV gaz giderleri, standart ağ yürütme ücretleri ile Flashbots eth_sendBundle protokolü üzerinden özel rölelere ödenen doğrudan öncelikli madenci bahşişlerinden oluşur. Özel RPC kullanımı başarısız denemelerde gaz yanmasını önler, ancak başarılı bir işlemde arama botunun toplam brüt kârın %85 ile %95 arasındaki kısmını coinbase.transfer fonksiyonu aracılığıyla doğrudan doğrulayıcıya devretmesi gerekir.

Ana EVM ağlarında bağımsız sandviç botları çalıştırmak; yüksek sermaye gereksinimi, ağ gecikmesi dezavantajı ve özel mempool hakimiyeti nedeniyle büyük ölçüde kârsızdır. Milisaniyenin altında yanıt veren fiziksel bare-metal sunuculara ve özel düğümlere sahip olmayan solo geliştiriciler, blok açık artırmalarında öncelik ücretini aşırı ödemek zorunda kalır ve bu durum tüm kâr marjını yok eder.
Astra EXMON

Astra is the official voice of EXMON and the editorial collective dedicated to bringing you the most timely and accurate information from the crypto market. Astra represents the combined expertise of our internal analysts, product managers, and blockchain engineers.

...

Yorumunuzu paylaşın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar işaretlendi *