Kapatmak için ESC'ye basın

Anti-MEV Stealth Swap: Büyük Final – Gönderim ve CLI

Evet, önceki iki makalede "güvenli iletişim kanalımızı" kurduk ve takas (swap) mantığını kodladık. Bu son bölümde ise aracı tamamlıyoruz. Blok bekleme döngüsünü uygulayacağız ve her şeyi kullanımı kolay bir Komut Satırı Arayüzü (CLI) içine paketleyeceğiz.

1. Gönderim Mantığı: Neden sadece "Gönder"e basıp geçemiyoruz?

Ethereum ağı yaklaşık her 12 saniyede bir blok üretir. Oluşturduğunuz paket (bundle) yalnızca belirli bir blok numarası için geçerlidir. Eğer paketiniz (örneğin düşük rüşvet/bahşiş nedeniyle) en yakın bloğa giremezse, bir sonraki blok numarasıyla paketi yeniden oluşturmanız gerekir.

Biz, Stealth Swap işlemimizi önümüzdeki 10 blok boyunca "ittirmeye" çalışan bir döngü kullanacağız.

 

2. Kod: Gönderim ve CLI Uygulaması

Final metodumuz olan sendBundle işlevini ve basit komut satırı argüman yönetimini ekleyelim.

import { FlashbotsBundleResolution } from "@flashbots/ethers-provider-bundle";

async function runStealthSwap(amountInEth: string) {
    const { wallet, flashbotsProvider, provider } = await initStealthProvider();
    const amountIn = ethers.parseEther(amountInEth);
    let currentBlock = await provider.getBlockNumber();

    console.log(`Başlangıç bloğu: ${currentBlock}`);

    // Paketi önümüzdeki 10 blok içinde göndermeye çalışıyoruz
    for (let i = 0; i < 10; i++) {
        const targetBlock = currentBlock + i;
        
        // Belirli bir blok için paketi yeniden oluştur (simülasyon dahil)
        const signedBundle = await createAndSimulateBundle(wallet, flashbotsProvider, provider, amountIn, targetBlock);
        
        if (!signedBundle) continue;

        const bundleSubmission = await flashbotsProvider.sendBundle(signedBundle, targetBlock);
        
        if ("error" in bundleSubmission) {
            console.error(`Gönderim hatası: ${bundleSubmission.error.message}`);
            continue;
        }

        console.log(`Paket gönderildi. ${targetBlock} numaralı blok bekleniyor...`);
        const waitResponse = await bundleSubmission.wait();
        
        if (waitResponse === FlashbotsBundleResolution.BundleIncluded) {
            console.log(`ZAFER! İşlem ${targetBlock} numaralı bloğa eklendi`);
            console.log(`Hash: https://etherscan.io/tx/${(await signedBundle)[0].hash}`); // Tahmini hash
            return;
        } else if (waitResponse === FlashbotsBundleResolution.BlockPassedWithoutInclusion) {
            console.log(`Kaçırdık. ${targetBlock} numaralı blok bizsiz geçti. Sonrakini deniyoruz...`);
        } else if (waitResponse === FlashbotsBundleResolution.AccountNonceTooHigh) {
            console.error("Hata: Nonce çok yüksek. Bekleyen işlemlerinizi kontrol edin.");
            return;
        }
    }
}

// Basit CLI arayüzü
const amount = process.argv[2] || "0.01";
runStealthSwap(amount);

Tabii ki şu ana kadar yaptıklarımız, Uniswap V3 üzerinden takas yapmak için sadece bir "Flashbots Merhaba Dünya" seviyesinde. Bunu gerçek bir üretim (production) aracına dönüştürmek için mantığı biraz daha keskinleştirmemiz gerekiyor.

 

import { ethers } from "ethers";
import { FlashbotsBundleProvider, FlashbotsBundleResolution } from "@flashbots/ethers-provider-bundle";
import * as dotenv from "dotenv";

dotenv.config();

const WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const ROUTER = "0xE592427A0AEce92De3Edee1F18E0157C05861564";
const QUOTER = "0x61fFe014bA17989E743c5F6cB21bF9697530B21e";

const ABI = [
    "function exactInputSingle((address tokenIn, address tokenOut, uint24 fee, address recipient, uint256 deadline, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96)) external returns (uint256 amountOut)",
    "function quoteExactInputSingle((address tokenIn, address tokenOut, uint256 amountIn, uint24 fee, uint160 sqrtPriceLimitX96)) external returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)",
    "function approve(address spender, uint256 amount) external returns (bool)",
    "function allowance(address owner, address spender) external view returns (uint256)",
    "function balanceOf(address account) external view returns (uint256)"
];

async function main() {
    const provider = new ethers.JsonRpcProvider(process.env.ETH_RPC_URL);
    const wallet = new ethers.Wallet(process.env.SENDER_PRIVATE_KEY, provider);
    const authSigner = new ethers.Wallet(process.env.FLASHBOTS_AUTH_KEY, provider);
    const flashbots = await FlashbotsBundleProvider.create(provider, authSigner);

    const quoter = new ethers.Contract(QUOTER, ABI, provider);
    const weth = new ethers.Contract(WETH, ABI, wallet);

    const baseAmount = ethers.parseEther(process.argv[2] || "0.1");
    const minThreshold = ethers.parseUnits(process.argv[3] || "200", 6);

    // --- ÖN KONTROL ---
    const balance = await weth.balanceOf(wallet.address);
    if (balance < baseAmount) throw new Error("YETERSİZ WETH");

    const allowance = await weth.allowance(wallet.address, ROUTER);
    if (allowance < baseAmount) {
        await (await weth.approve(ROUTER, ethers.MaxUint256)).wait();
    }

    let nonce = await wallet.getNonce();
    let lastQuote = 0n;
    let lastExecutionBlock = 0;

    provider.on("block", async (block) => {
        try {
            // --- RASTGELE ATLAMA (Bot izini gizler) ---
            if (Math.random() < 0.6) return;

            const quote = await quoter.quoteExactInputSingle.staticCall({
                tokenIn: WETH,
                tokenOut: USDC,
                amountIn: baseAmount,
                fee: 3000,
                sqrtPriceLimitX96: 0
            });

            // --- EŞİK KONTROLÜ (Threshold) ---
            if (quote.amountOut < minThreshold) return;

            // --- DEĞİŞİM TESPİTİ ---
            if (lastQuote !== 0n) {
                const diff = (quote.amountOut * 1000n) / lastQuote;
                // Değişim %0.3'ten azsa pas geç
                if (diff > 997n && diff < 1003n) return;
            }

            // --- BEKLEME SÜRESİ (Cool Down) ---
            if (block - lastExecutionBlock < 2) return;

            // --- RASTGELE MİKTAR (Bot imzasını bozar) ---
            const randomFactor = BigInt(95 + Math.floor(Math.random() * 10)); // %95–105 arası
            const amountIn = (baseAmount * randomFactor) / 100n;

            // --- KAYMA PAYI (Slippage) ---
            const minOut = (quote.amountOut * 995n) / 1000n;

            const feeData = await provider.getFeeData();
            const tx = {
                to: ROUTER,
                data: new ethers.Interface(ABI).encodeFunctionData("exactInputSingle", [{
                    tokenIn: WETH,
                    tokenOut: USDC,
                    fee: 3000,
                    recipient: wallet.address,
                    deadline: Math.floor(Date.now() / 1000) + 90,
                    amountIn: amountIn,
                    amountOutMinimum: minOut,
                    sqrtPriceLimitX96: 0
                }]),
                chainId: 1,
                type: 2,
                gasLimit: 250000,
                maxFeePerGas: feeData.maxFeePerGas,
                maxPriorityFeePerGas: feeData.maxPriorityFeePerGas || 2n,
                nonce: nonce
            };

            const signed = await flashbots.signBundle([{ signer: wallet, transaction: tx }]);
            const target = block + 1;

            const sim = await flashbots.simulate(signed, target);
            if ("error" in sim) return;

            const sub = await flashbots.sendBundle(signed, target);
            if ("error" in sub) return;

            const res = await sub.wait();
            nonce++; // KRİTİK
            if (res === FlashbotsBundleResolution.BundleIncluded) {
                console.log("İŞLEM TAMAMLANDI, BLOK:", target);
                process.exit(0);
            }

            lastQuote = quote.amountOut;
            lastExecutionBlock = block;
        } catch (e) {
            // Sessiz mod
        }
    });
}

main();

 

3. Anti-MEV Stealth Swap Nasıl Kullanılır?

1. Kurulum

npm install ethers @flashbots/ethers-provider-bundle dotenv

2. .env Dosyasını Oluşturun

ETH_RPC_URL=https://mainnet.infura.io/v3/ANAHTARINIZ
SENDER_PRIVATE_KEY=OZEL_ANAHTARINIZ
FLASHBOTS_AUTH_KEY=HERHANGI_YENI_BIR_OZEL_ANAHTAR

3. Cüzdan Hazırlığı

Olmazsa olmazlar:

  • Cüzdanda Ethereum (ETH) bulunmalı → Gaz ücretleri için.
  • Ve Wrapped Ether (WETH) → Takas işlemi için.

Eğer WETH'iniz yoksa: Önce herhangi bir arayüzden (örneğin Uniswap) ETH'lerinizi WETH'e çevirin.

4. Çalıştırma

node app.js 0.1 200

Parametreler:

  • 0.1 → Ne kadar WETH takas edilecek.
  • 200 → USDC cinsinden kabul edilebilir minimum miktar.

5. Nasıl Çalışıyor?

Başlattıktan sonra:

  • WETH bakiyesi kontrol edilir.
  • Onay (approve) verilir (sadece 1 kez).
  • Betik blokları dinlemeye başlar.
  • Her blokta:
    • Bazen rastgele pas geçer (iz gizleme).
    • Quoter üzerinden fiyat alır.
    • Eşik değerini kontrol eder.
    • Fiyat değişimini kontrol eder (durgunluk testi).
    • İşlem boyutunu rastgele değiştirir.
    • Simülasyon yapar.
    • Flashbots üzerinden gönderir.

6. İşlem Ne Zaman Gerçekleşir?

  • Fiyat ≥ belirtilen eşik değeri ise.
  • Fiyat değişmişse (hareket varsa).
  • Bekleme süresi dolmuşsa.
  • Simülasyon başarılıysa.

7. Sonuç

Konsolda şunu gördüğünüzde:

EXECUTED: 19483921

Anlamı:

  • Takas başarıyla yapıldı.
  • Betik görevini bitirdi.

8. Önemli Parametreler
Eşik (İkinci argüman)

node app.js 0.1 220

Yüksek eşik =

  • Daha az işlem tetiklenmesi.
  • Daha iyi fiyat yakalama şansı.

Miktar

node app.js 0.05 200

Düşük miktar =

  • Piyasa üzerinde daha az etki.
  • Daha düşük risk.

9. Neyi Anlamak Önemli?

  • Bu her zaman en iyi fiyatı garanti etmez.
  • Tüm saldırı türlerine karşı tam koruma sağlamaz.
  • Ancak "av" olma ihtimalinizi ciddi şekilde düşürür.

10. Ne Zaman Kullanmamalı?

  • Eğer "slippage" (fiyat kayması) mantığını bilmiyorsanız.
  • Eğer yeterli bakiyeniz yoksa.
  • Ağ aşırı yoğunsa.

Özetle

  • Çalıştırmak için sadece 1 komut yeterli.
  • Tam otomatik çalışır.
  • Flashbots üzerinden "sessizce" takas yapar.

Bu kod:

  • Profesyonel MEV botlarını her zaman yenemez.
  • Her senaryoda sizi koruyamaz.
  • Size sihirli bir avantaj sağlamaz.

ANCAK:
👉 Artık kolay bir lokma olmazsınız.

 

Bu araç sadece buzdağının görünen kısmı. Arbitraj, likidasyon veya büyük miktarda likiditeyi güvenle taşımak için geliştirilip ölçeklendirilebilir.

Unutmayın: Blokzincirinin bu "karanlık ormanında" en yüksek sesle bağıran değil, sessizce yürümeyi bilen hayatta kalır.

Bu materyal EXMON Academy için hazırlanmıştır. Mainnet üzerinde dikkatli deneyler yapın ve kayma payı (slippage) ayarlarınızı her zaman kontrol edin!

Sying Yu

I am a blockchain developer specializing in building secure, scalable, and innovative decentralized solutions. My expertise covers smart contracts, payment systems, and integrating crypto with fiat to optimize financial workflows. I thrive on creating modern, efficient tools for the evolving digital economy....

Yorumunuzu paylaşın

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