Kapatmak için ESC'ye basın

Anti-MEV Stealth Swap: Bundle Oluşturma ve Simülasyon

İlk bölümde "güvenli iletişim hattımızı" kurmuştuk. Bu bölümde işin kalbine, yani swap mantığını yazma kısmına geçiyoruz. Görevimiz; Uniswap V3 için sadece gizli kalacak değil, aynı zamanda gerçekleşmesi garanti altına alınmış bir işlem hazırlamak.

1. Swap İşleminin Hazırlanması

Örnek olarak bir ETH - USDC swap'i kurgulayalım. İşlemin bir bundle (paket) içinde geçerli olabilmesi için, objeyi ağa önceden yayınlamadan, arka planda hazırlamamız gerekiyor.

Masada şunların olması şart:

  • Uniswap V3 Router adresi.
  • exactInputSingle fonksiyonu için (en azından minimal düzeyde) bir ABI.
  • Öncelik payını hesaba katan bir gaz hesaplaması.

 

Altın Kural: Flashbots paketlerinde standart gasPrice devre dışı kalır; yerine maxFeePerGas ve maxPriorityFeePerGas gelir. Paketinizin bloğa girip girmeyeceğini belirleyen asıl şey priorityFee, yani doğrulayıcıya (validator) verdiğiniz "bahşiştir".

 

 

2. Kod: Oluşturma ve Simülasyon

Projemize swap.ts dosyasını ekleyelim. Buradaki asıl olay .simulate() metodunda bitiyor. Bu, Flashbots'un en büyük kozu: Gerçek gaza tek kuruş harcamadan, işlemin blokzincirinin o anki durumunda çalışıp çalışmayacağını test etmenizi sağlar.

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

// Uniswap V3 Router ile etkileşim için gereken en temel ABI
const ROUTER_ABI = [
    "function exactInputSingle((address tokenIn, address tokenOut, uint24 fee, address recipient, uint256 deadline, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96)) external payable returns (uint256 amountOut)"
];

const ROUTER_ADDRESS = "0xE592427A0AEce92De3Edee1F18E0157C05861564";

export async function createAndSimulateBundle(wallet: ethers.Wallet, flashbotsProvider: any, provider: ethers.Provider) {
    const block = await provider.getBlock("latest");
    const nextBlockNumber = block!.number + 1;

    // 1. Arayüzü oluştur ve işlem verilerini hazırla
    const iface = new ethers.Interface(ROUTER_ABI);
    const deadline = Math.floor(Date.now() / 1000) + 60 * 20; // 20 dakikalık süre
    
    const amountIn = ethers.parseEther("0.1"); // 0.1 ETH swap ediyoruz
    const params = {
        tokenIn: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
        tokenOut: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
        fee: 3000, // %0.3 havuz
        recipient: wallet.address,
        deadline: deadline,
        amountIn: amountIn,
        amountOutMinimum: 0, // Canlıda her zaman slippage (fiyat kayması) hesaplayın!
        sqrtPriceLimitX96: 0
    };

    const data = iface.encodeFunctionData("exactInputSingle", [params]);

    // 2. İşlem yapısı
    const transaction = {
        to: ROUTER_ADDRESS,
        value: amountIn,
        data: data,
        chainId: 1,
        type: 2, // EIP-1559
        gasLimit: 250000,
        maxFeePerGas: ethers.parseUnits("50", "gwei"),
        maxPriorityFeePerGas: ethers.parseUnits("2", "gwei"), // Doğrulayıcıya giden "rüşvet"
        nonce: await wallet.getNonce()
    };

    // 3. İmzalı paketi (bundle) oluştur
    const signedBundle = await flashbotsProvider.signBundle([
        {
            signer: wallet,
            transaction: transaction
        }
    ]);

    // 4. SİMÜLASYON (Kritik aşama)
    console.log("Paket simülasyonu başlatılıyor...");
    const simulation = await flashbotsProvider.simulate(signedBundle, nextBlockNumber);

    if ("error" in simulation) {
        console.error(`Simülasyon başarısız: ${simulation.error.message}`);
        return;
    }

    console.log("Simülasyon canavar gibi!", JSON.stringify(simulation, null, 2));
    return signedBundle;
}

 

3. Teknik Detay: Simülasyon Neden Şart?

"Genel" mempool'da, eğer işleminiz başarısız olursa (gaz limitinin yetmemesi veya fiyatın değişmesi gibi), işlem yine de bloğa girer ve siz o gaz ücretini kuzu kuzu ödersiniz.

Flashbots dünyasında ise:

  • Eğer simülasyon hata verirse, paketi hiç göndermezsiniz. Zararınız sıfır olur.
  • Paket gönderilse bile, eğer bloktaki şartlar değişmişse ve işlem kârsız hale gelmişse; doğrulayıcı paketi görmezden gelir.

Özetle: Gaz ücretini sadece "Stealth Swap" işleminiz gerçekten gerçekleştiğinde ödersiniz.

4. "Rüşvet" (Priority Fee) Nasıl Hesaplanır?

Doğrulayıcılar, paketleri kendilerine sağladığı kâra göre sıraya dizerler. Bir paketin kârlılığı (Gas Price Score) şu şekilde hesaplanır:

kârlılık formülü
 

Sıradan bir swap yapıyorsanız 1-2 gwei'lik bir maxPriorityFeePerGas genelde yeterlidir. Ancak piyasanın çok hareketli olduğu anlarda, bu özel yollarda bile bloğa girmek için rekabet kızışabilir.

 

Şu an elimizde ne var?

İmzalanmış, doğrulanmış ve gönderilmeye hazır bir paketimiz var. Uniswap kodunun düzgün çalışacağından ve cüzdandaki bakiyenin tüm masrafları karşılayacağından artık eminiz.

Bir sonraki (ve son) bölümde: Blok bekleme döngüsünü yazacak, paketi gerçek anlamda ağa salacak ve aracımız için kullanışlı bir CLI arayüzü oluşturacağız.

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 *