687 показания
687 показания

В тъмната гора: Инженерна работа Дефи Арбитраж

от Simone Convertini45m2025/05/31
Read on Terminal Reader

Твърде дълго; Чета

Как да се изгради работен DeFi арбитраж бот, който се възползва от различията в цените в AMMs.
featured image - В тъмната гора: Инженерна работа Дефи Арбитраж
Simone Convertini HackerNoon profile picture

1. Introduction —В тъмната гора

1 Въведение -

Късно една нощ Дан Робинсън, изследовател в инвестиционната фирма Paradigm, видял спешен разговор в канала Uniswap Discord.дведруг потребител, но към самия договор Uniswap, където те изглеждаха непоправимо изгубени.

Робинсън, обаче, видя един блясък на надежда. Той осъзна, че всеки може да задействаburnФункция на договора, публична заповед, която ще принуди договора да освободи заловените токени на лицето, което го е повикало.

Признавайки възможността да бъде герой с бяла шапка, Робинсън подготви спасителната транзакция. Но той знаеше, че не е сам. Ethereum mempool - обществената чакалня за чакащи транзакции - е ловна площадка за усъвършенствани ботове, известни като "генерализирани фронтунери". Тези хищници непрекъснато сканират за всякакви печеливши действия, незабавно го копират и заменят оригиналния адрес със собствения си, за да откраднат наградата.

За да ги преодолее, Робинсън измисли умна сделка от две части, надявайки се двете части да бъдат изкопани едновременно, без да оставят прозорец за прихващане.Това не работи.В момента, в който се появи първата му сделка, ботът я откри, възпроизведе цялата стратегия и открадна 12 000 долара, преди дори да може да бъде потвърдена втората сделка на Робинсън.

В сега известното есе за инцидента, Робинсън даде име на тази враждебна, невидима екосистема.Ethereum is a Dark Forest.

В тази статия ще се впуснем в проектирането на система, способна да чете операции в реално време и данни от транзакции с блокчейн, с цел извършване на арбитраж.mathematical models underlying AMM pricingДълбочи се вalgorithms for opportunity detection and optimal price entryОпределяне наarchitectural componentsот нашия бот, и да обсъдятcritical strategiesнеобходими за успешно и безопасно изпълнение на арбитраж в тази среда с високи залози.


The DeFi Landscape: AMMs, ликвидност и арбитражни възможности

"Тъмната гора", описана в нашето въведение, не е просто враждебна среда; това е жизнена екосистема, изградена върху нова финансова парадигма: Децентрализирано финансиране (DeFi). В основата си, DeFi има за цел да възстанови традиционните финансови услуги в блокчейн мрежи, премахвайки необходимостта от посредници чрез използването на самоусъвършенстващи се интелигентни договори.

Автоматизирани пазарни производители (AMMs): гръбнакът на децентрализирания обмен

Традиционните борси разчитат на книги за поръчки, където купувачите и продавачите поставят оферти и искания, а централният двигател за съвпадение улеснява търговията. DeFi въвежда радикално различен модел: Автоматизиран пазар (АММ). Вместо да съвпадат купувачите и продавачите директно, АММ оползотворяват ликвидни басейни – интелигентни договори, които държат резерви от два или повече токена – за да улеснят търговията.

Цената на активите в един АММ пул се определя алгоритмично отconstant product formulaСъздаден от Uniswap:

Тук x и y представляват количествата на двата токена в ликвидния басейн, а k е константа. Когато потребителят търгува един токен за друг, количествата на x и y в басейна се променят, но техният продукт k трябва да остане константен. Този механизъм динамично коригира цената: закупуването на повече от токена А ще намали количеството му в басейна, като по този начин увеличава цената му по отношение на токена B и обратно.bonding curve, който диктува наличните ценови точки за сделки.

От този модел е възможно детерминистично да се изчисли изходната сума (dy) от суап, като се вземе предвид входната сума (dx) и резервите преди суап на двата токена (x и y):

Key characteristics of AMMs:

  • Винаги на ликвидност: За разлика от книгите за поръчки, които могат да станат тънки, AMM винаги предлагат ликвидност, докато има токени в басейна.
  • Без разрешение: Всеки може да стане доставчик на ликвидност или да търгува на АММ, без да се нуждае от одобрение.
  • Откриване на цени: Цените се определят от съотношението на активите в банката, като се коригират с всяка търговия.
  • Плъзгане: Големите сделки могат значително да преместят цената в един басейн, което води до явление, известно като плъзгане, където изпълнената цена е по-лоша от цитираната цена.

Докато моделът x⋅y=k (често наричан Uniswap V2) постави основата, AMMs са се развили. Uniswap V3, например, въведе “концентрирана ликвидност” (CLAMM), което позволява на LPs да разпределят своя капитал в рамките на определени ценови диапазони. Това значително подобри капиталовата ефективност, но също така увеличи сложността за LPs и, следователно, за арбитражи, които трябва да проследяват ликвидността в различни диапазони.we will primarily focus on AMMsизползването на постоянната формула на продукта (като Uniswap V2-стилни басейни), тъй като те осигуряват основно разбиране, преди да се справят с по-сложни модели.

The Essence of Arbitrage in DeFi

Арбитражът, в най-чистата си форма, е едновременната покупка и продажба на актив на различни пазари, за да се извлече полза от разликата в цената му. В DeFi това се превежда в експлоатация на ценовите различия между различни AMM басейни, или между AMM и централизирана борса (CEX), за една и съща токенова двойка. Неразрешената природа на DeFi и фрагментираната ликвидност в различните протоколи създават плодородна почва за тези възможности. Високата волатилност и липсата на регулиране в това възникващо финансово пространство често водят до значителни ценови отклонения, които са жизненоважна сила на арбитражите.

Видове арбитражни възможности в DeFi

  • Например, ако 1 ETH търгува за 2000 DAI на Uniswap A, но 1 ETH търгува за 2010 DAI на Uniswap B, арбитърът може да закупи ETH на Uniswap A с DAI и незабавно да продаде този ETH за DAI на Uniswap B, потапяйки 10 DAI разликата (минус такси за газ и пропускане).
  • Триъгълният арбитраж (Multi-Leg): Този тип арбитраж включва три или повече активи в рамките на една и съща борса (или в множество борси), за да образува печеливш цикъл. Например, арбитър може да започне с Token A, да го обменя за Token B, след това Token B за Token C, и накрая Token C да се върне към Token A, завършвайки с повече от Token A, отколкото са започнали. Общ пример за Uniswap може да бъде: WETH -> DAI -> USDC -> WETH.
  • Флаш арбитраж за заеми: Мощен и уникален аспект на DeFi, флаш заеми позволяват на потребителите да заемат необезпечени активи, да ги използват за серия от транзакции (като арбитраж) и да изплащат заема – всичко в рамките на една блокчейн транзакция. Ако цялата последователност от операции (заем, търговия, изплащане) не може да бъде завършена успешно в рамките на тази отделна транзакция, цялата транзакция се връща, сякаш никога не се е случило. Това премахва необходимостта от значителен авансов капитал и значително намалява бариерата за влизане за мащабен арбитраж, но това също означава, че цялата арбитражна стратегия трябва внимателно да бъде оркестрирана в рамките на една атомна операция. Ние ще включим опция за флаш

Състезанието за печалба: предизвикателства и конкуренция

Дефи пейзажът е високоефективен пазар. Разликите в цените са краткотрайни, често съществуващи само за милисекунди, преди да бъдат експлоатирани от усъвършенствани ботове.

  • Gas Fees: Every interaction with a smart contract incurs a transaction fee (gas), which can vary significantly based on network congestion. A profitable arbitrage opportunity must yield enough profit to cover these costs.

  • Slippage: The larger the trade relative to the pool’s liquidity, the greater the slippage, eroding potential profits. Accurately modeling slippage is crucial for calculating true profitability.

  • Latency: The speed at which an arbitrage bot can detect an opportunity, calculate the optimal trade, construct a transaction, and submit it to the network is paramount. Even milliseconds can make the difference between profit and loss.

  • Frontrunning and MEV: As discussed in the introduction, the “Dark Forest” is dominated by generalized frontrunners. These bots actively monitor the mempool for pending profitable transactions, replicate them, and submit their own transaction with a higher gas price to ensure their transaction is included in a block before the original one. This phenomenon falls under the umbrella of Maximal Extractable Value (MEV), representing the total value that can be extracted from block production in excess of the standard block reward and gas fees by arbitraging, liquidating, or reordering transactions within a block. Successfully navigating this environment often requires advanced strategies like leveraging MEV-Boost relays or private transaction pools. To mitigate the risk of being intercepted in public mempools, our implementation will primarily operate on Base, an EVM-compatible Layer 2 (L2) blockchain. Base’s architecture, which currently does not expose a public mempool in the same manner as Ethereum’s Layer 1, offers a different environment for transaction submission, potentially reducing traditional frontrunning risks.

  • Complexity of AMMs: As AMMs evolve (e.g., Uniswap V3’s concentrated liquidity), the mathematical modeling and state tracking required for accurate arbitrage calculations become significantly more complex.

    Understanding these foundational elements of DeFi, from the mechanics of AMMs to the cut-throat nature of arbitrage competition, sets the stage for designing a robust and effective arbitrage bot. In the next chapter, we will begin to lay out the architectural blueprint for such a system.

Архитектурно проектиране: Изграждане на арбитражна ботова инфраструктура

Изграждането на печеливш арбитражен бот в „Тъмна гора“ на DeFi изисква архитектура, която дава приоритет на скоростта, надеждността и точността. Всяка милисекунда има значение и способността да се обработват данни в реално време, да се идентифицират възможностите и да се изпълняват бързо сделки е от първостепенно значение.

Go е избран като първичен език за развитие поради изключителната си производителност, силните си примитиви (goroutines и канали) и силната екосистема за мрежово програмиране и системни взаимодействия на ниско ниво. Тези характеристики са от решаващо значение за управлението на високия пропуск на blockchain данни и необходимостта от паралелна обработка в система за арбитраж в реално време.go-ethereumПървият клиент на Ethereum.

Архитектурата на бота е структурирана катоevent-driven systemсъстояща се от няколко независими услуги (модули), всеки от които работи в паралелни процеси (горутини). Тези услуги общуват асинхронно чрез изпращане на съобщения чрез канали Go, осигурявайки слабо свързан и високо отзивчив дизайн.

Цялостна архитектура на системата

Инфраструктурата на арбитражния бот може да се визуализира като тръбопровод, където данните преминават от блокчейна, се обработват и анализират и кулминират в изпълнението на печеливши сделки.

  • Blockchain Data Reader Service: Responsible for real-time ingestion of blockchain events data.

  • Market Graph Service: Maintains an in-memory representation of the DeFi market and identifies arbitrage paths.

  • Arbitrage Strategy Service: Evaluates detected opportunities for profitability and prepares trade instructions.

  • Transaction Builder Service: Constructs and dispatches blockchain transactions.

  • Honeywall Service: A post-execution checker that enhances security and maintains market integrity by identifying and blacklisting malicious pools.

    This modularity allows each service to focus on a specific task, minimizing dependencies and optimizing performance for its particular workload. Communication between services is strictly asynchronous, leveraging Go’s channels for message passing, which naturally facilitates a non-blocking and highly concurrent operation.

Блокчейн услуга за четене на данни: очите и ушите на нашия бот в потока от данни

Тази услуга действа като основен интерфейс на бота с суровите данни в реално време, които преминават през блокчейна.В „Тъмната гора“ информацията е валута и способността ни да я поглъщаме бързо и точно е от първостепенно значение.extract crucial financial data pointsТова ще подхранва нашия арбитражен механизъм за вземане на решения.

  • Свързване и поглъщане на данни: Reader се свързва с блокчейн възел чрез WebSockets. Тази постоянна, двупосочна връзка позволява незабавно получаване на нови заглавия на блокове и, по-важното, дневници на събития, издадени от интелигентни договори. Услугата е конфигурирана специално за слушане на Swap, Mint, Burn и Sync събития от интелигентни договори на Децентрализирана Биржа (DEX). Тези събития са от решаващо значение, тъй като показват промени в резервите на ликвидните басейни, пряко влияещи на цените на токените.
  • New Block Headers: Чрез абониране за нови блокови заглавия получаваме незабавно уведомление за промени в състоянието. Всеки нов блок представлява потвърдена снимка на текущата реалност на блокчейна, включително нови транзакции, актуализирани баланси и нови състояния на ликвидния басейн.
func (er *EthereumReader) SubscribePairs() error {

	parsedABI := constants.PairAbi

	// Set up the filter
	query := ethereum.FilterQuery{
		Topics: [][]common.Hash{
			{
				parsedABI.Events["Swap"].ID,
				parsedABI.Events["Mint"].ID,
				parsedABI.Events["Burn"].ID,
				parsedABI.Events["Sync"].ID,
			},
		},
	}

	logs := make(chan types.Log)

	sub, err := er.ethClient.SubscribeFilterLogs(context.Background(), query, logs)
	if err != nil {
		return err
	}

	// Start Routine to read swaps events
	log.Println("[READING SWAPS...]")
	go func() {
		for {
			select {
			case err = <-sub.Err():
				log.Println("[RESET CONNECTION...] Subscription error: ", err)
				pairInfo := GraphMessage{
					Ok: false,
				}
				*er.pairChan <- pairInfo

				time.Sleep(5 * time.Minute)
				er.ethClient = clients.ResetConnection()
				er.SubscribePairs()

				return
			case vLog := <-logs:
				start := time.Now()

				pairAddress := vLog.Address
				if er.filter.IsPairBlackListed(pairAddress.Hex()) {
					continue
				}

				blockNumber := vLog.BlockNumber
				if blockNumber > er.currentBlockNumber {
					// New block detected, reset cache
					er.lastUpdatedBlock = nil
					er.lastUpdatedBlock = make(map[common.Address]uint64)
					er.currentBlockNumber = blockNumber
				}

				// Check if already updated for this pair in current block
				if _, exists := er.lastUpdatedBlock[pairAddress]; exists {
					continue
				}

				t0, t1, f, r0, r1, err := er.getPairDataFromHelper(pairAddress)
				if err != nil {
					continue
				}

				dex := f.String()
				router, err := constants.GetRouterAddressFromFactory(dex)
				if err != nil {
					continue
				}

				// Update cache
				er.lastUpdatedBlock[pairAddress] = blockNumber
				elapsed := time.Until(start)

				pairInfo := GraphMessage{
					Ok:       true,
					DexCheck: true,
					Pair:     pairAddress.Hex(),
					Token0:   Token{Address: t0.Hex()},
					Token1:   Token{Address: t1.Hex()},
					Reserve0: r0,
					Reserve1: r1,
					Dex:      router,
					GetTime:  elapsed,
				}

				*er.pairChan <- pairInfo
			}
		}
	}()

	return nil
}
  • За да се оптимизира ефективността и да се намалят излишните повиквания по веригата, Reader използва персонализиран интелигентен договор, написан специално за тази цел. Този договор служи като агрегатор, като осигурява единен, оптимизиран повикване за извличане на резервите и друга агрегирана информация за множество двойки ликвидност. Ключова функционалност на този персонализиран договор е неговата вградена предварителна проверка за общи характеристики на измами или прекомерни търговски данъци в един басейн преди връщането на данните.
  • Основната логика се крие в метода checkPair, който оценява безопасността на една двойка токени и връща обобщени данни.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract ArbHelperMap {
    mapping(address => address) public factoryToRouter;
    address public owner;
    
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }
    
    constructor() {
        owner = msg.sender;
        // Pre-populate known mappings
        factoryToRouter[0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6] = 0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24;
        factoryToRouter[0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E] = 0x8cFe327CEc66d1C090Dd72bd0FF11d690C33a2Eb;
        factoryToRouter[0xFDa619b6d20975be80A10332cD39b9a4b0FAa8BB] = 0x327Df1E6de05895d2ab08513aaDD9313Fe505d86;
        factoryToRouter[0x71524B4f93c58fcbF659783284E38825f0622859] = 0x6BDED42c6DA8FBf0d2bA55B2fa120C5e0c8D7891;
        factoryToRouter[0x3E84D913803b02A4a7f027165E8cA42C14C0FdE7] = 0x8c1A3cF8f83074169FE5D7aD50B978e1cD6b37c7;
        factoryToRouter[0x9A9A171c69cC811dc6B59bB2f9990E34a22Fc971] = 0x1b7655aa64b7BD54077dE56B64a0f92BCba05b85;
    }
    
    function addFactoryRouter(address factory, address router) external onlyOwner {
        require(factory != address(0) && router != address(0), "Zero address");
        factoryToRouter[factory] = router;
    }
    
    struct Result {
        bool success;
        address token0;
        address token1;
        address factory;
        uint112 reserve0;
        uint112 reserve1;
    }
    
    // Helper function to get pair data
    function _getPairData(address pairAddress) private view returns (
        bool success,
        address token0,
        address token1,
        address factory,
        uint112 reserve0,
        uint112 reserve1,
        address router
    ) {
        success = false;
        
        try IPair(pairAddress).token0() returns (address _token0) {
            token0 = _token0;
            
            try IPair(pairAddress).token1() returns (address _token1) {
                token1 = _token1;
                
                try IPair(pairAddress).factory() returns (address _factory) {
                    factory = _factory;
                    
                    try IPair(pairAddress).getReserves() returns (uint112 r0, uint112 r1, uint32) {
                        reserve0 = r0;
                        reserve1 = r1;
                        
                        router = factoryToRouter[factory];
                        if (router != address(0)) {
                            success = true;
                        }
                    } catch {}
                } catch {}
            } catch {}
        } catch {}
    }
    
    // Helper function to check if pair passes tax limit
    function _checkTaxLimit(
        address router,
        address token0,
        address token1,
        uint amountIn,
        uint maxTaxPermille
    ) private view returns (bool) {
        address[] memory path = new address[](2);
        path[0] = token0;
        path[1] = token1;
        
        try IRouter(router).getAmountsOut(amountIn, path) returns (uint[] memory buyOuts) {
            if (buyOuts.length < 2) return false;
            
            address[] memory reversePath = new address[](2);
            reversePath[0] = token1;
            reversePath[1] = token0;
            
            try IRouter(router).getAmountsOut(buyOuts[1], reversePath) returns (uint[] memory sellOuts) {
                if (sellOuts.length < 2) return false;
                
                uint minReturn = amountIn - (amountIn * maxTaxPermille / 1000);
                return sellOuts[1] >= minReturn;
            } catch {
                return false;
            }
        } catch {
            return false;
        }
    }
    
    function checkPair(address pairAddress, uint amountIn, uint maxTaxPermille) external view returns (Result memory r) {        
        // Initialize result with default values
        r.success = false;
        
        // Skip processing if pair address is zero
        if (pairAddress == address(0)) return r;
        
        // Get pair data
        bool success;
        address token0;
        address token1;
        address factory;
        uint112 reserve0;
        uint112 reserve1;
        address router;
        
        (success, token0, token1, factory, reserve0, reserve1, router) = _getPairData(pairAddress);
        
        // If we couldn't get pair data or there's no router, return early
        if (!success) return r;
        
        // Check tax limits
        bool passedTaxCheck = _checkTaxLimit(router, token0, token1, amountIn, maxTaxPermille);
        
        // Populate result if tax check passed
        if (passedTaxCheck) {
            r.success = true;
            r.token0 = token0;
            r.token1 = token1;
            r.factory = factory;
            r.reserve0 = reserve0;
            r.reserve1 = reserve1;
        }
        
        return r;
    }
}
  • Събитие-ориентирана комуникация: След получаване и обработка на тези събития, Reader нормализира данните и изпраща актуализации (например нови резервни стойности за конкретен пул) като съобщения чрез Go канал до Market Graph Service.

Market Graph Service: Картиране на пазара на DeFi

Market Graph Service е централната разузнавателна единица, която поддържа представяне в реално време и в памет на пазара DeFi.directed graphКъде е :

  • Нодовете представляват отделните криптовалути (например WETH, USDC, DAI).
  • Крайници: Представляват ликвидни басейни на различни DEXes (напр. Uniswap V2 ETH/DAI басейн, SushiSwap USDC/WETH басейн).
  • Структура на данните и актуализации: Тази услуга получава актуализации от услугата Blockchain Data Reader чрез канали.При получаване на нови резервни данни за пул, тя актуализира съответния ръб в диаграмата.
  • Точност с BigInt: Всички изчисления, включващи суми на токени и обменни курсове, използват математическия/голям пакет на Go (BigInt или BigFloat). Това е от решаващо значение за поддържане на произволна точност, предотвратяване на неточности в плаващите точки, които могат да доведат до пропуснати възможности или неправилни изчисления на печалбата.
  • Арбитражният алгоритъм: Алгоритъмът на Bellman-Ford: В сърцето на тази услуга е функцията FindArbitrage, която използва графичен алгоритъм, по-специално алгоритъмът на Bellman-Ford. Този алгоритъм е уникално способен да открива отрицателни цикли в графа, което е точно това, което съответства на арбитражна възможност в нашия пазарния модел (където логаритмичните обменни курсове се използват като ръбни тежести). За разлика от много други алгоритми на графичната теория, които се фокусират върху намирането на най-ефективния път, способността на Bellman-Ford да открива отрицателни цикли го прави изключително ефективен както за DeFi, така и за количествени финансови приложения

Арбитражна стратегия: идентифициране и оптимизиране на печалбата

Абонирайте се за актуализации на събития отMarket Graph ServiceСлужбата за арбитражна стратегия непрекъснато наблюдава графиката на пазара за новооткритите арбитражни пътища.

  • Оценка на възможностите: Всеки път, когато графикът се актуализира или потенциалният арбитражен път се идентифицира от FindArbitrage, тази услуга влиза в действие.
  • Оптимално изчисляване на сумата на входа (Convex Optimization): Критична стъпка е определянето на оптималната сума на входа (dx) за арбитражната последователност. Това е нетривиален проблем, тъй като рентабилността е нелинейна функция на сумата на входа, както е показано в статията „Анализ на пазарите на Uniswap“. Тя се влияе от пропускането и таксите в множество суапи. Услугата решава този проблем като проблем за конвексна оптимизация, като използва пакета Go’s gonum/optimize. Това гарантира, че избраната сума на входа максимизира нетната печалба след отчитане на всички променливи.
  • Симулация на суапове: Преди да се ангажира с транзакция, услугата извършва симулирано изпълнение на всички суапове в рамките на открития арбитражен път, като използва постоянната формула на продукта и изчислената оптимална сума на входа.По време на тази симулация минималните суми на изхода също се определят за всяка стъпка на междинния суап. Това гарантира, че в случай на неочаквано ниски реални изходи (например поради внезапни колебания на цените или високи свлачища по веригата), транзакцията ще се върне с минимална загуба на газ, вместо да продължи с нерентабилна или загуба на търговия.
  • Всички такси: Включително такси за търговия с DEX (напр. 0,3% за Uniswap V2).
  • Плъзгане: Точно моделиране на ценовия ефект на всяка търговия в рамките на последователността.
  • Разходи за газ: Оценка на разходите за газ, необходими за цялата транзакция, като се вземат предвид веригата (базата) и текущите условия на мрежата.
  • Праг на печалбата: Само ако изчислената нетна печалба е най-малко 0,5% от първоначалния размер на входа (или конфигурируем праг), възможността се счита за жизнеспособна.
  • Уведомление за изпълнение: Ако печеливша възможност отговаря на критериите, услугата за арбитражна стратегия събира всички необходими подробности - подредената последователност от суапи (краища), оптималния размер на входа и всички други съответни параметри - и изпраща уведомление чрез канал Go до услугата за изграждане на транзакции.

Услуга за изграждане на транзакции: Swift Execution

Услугата Transaction Builder е изпълнителната ръка на бота, натоварена с бързото изграждане и подаване на арбитражната транзакция до блокчейна.

  • Строителство на транзакции: След като получи възможност от Арбитражната стратегия, тази услуга незабавно започва да изгражда транзакцията на атомния блокчейн.
  • Интеракция на интелигентни договори (атомни суапи): Тази услуга взаимодейства с персонализиран интелигентен договор, специално предназначен да изпълнява всички арбитражни операции (многобройни суапи) в рамките на една, атомна транзакция.
  • Ето функцията Solidity, която обработва арбитражно изпълнение без флаш заем, изисквайки от собственика (бота) да финансира първоначалната сумаIn:
struct SwapStep {
      address router;
      address[] path;
      uint minOut;
}

function executeArb(
    address inputToken,
    uint amountIn,
    SwapStep[] calldata steps,
    uint minFinalOut
) external onlyOwner returns (uint finalAmountOut) {
    require(steps.length > 0, "No steps");

    // Transfer tokens from msg.sender to contract
    require(IERC20(inputToken).transferFrom(msg.sender, address(this), amountIn), "Transfer in failed");

    address currentToken = inputToken;
    uint currentAmount = amountIn;

    for (uint i = 0; i < steps.length; i++) {
        SwapStep calldata step = steps[i];
        require(step.path[0] == currentToken, "Path mismatch");

        address outputToken = step.path[step.path.length - 1];

        // Save balance before swap
        uint balanceBefore = IERC20(outputToken).balanceOf(address(this));

        // Safe approve
        require(IERC20(currentToken).approve(step.router, 0), "Reset approve failed");
        require(IERC20(currentToken).approve(step.router, currentAmount), "Approve failed");

        IUniswapV2Router(step.router).swapExactTokensForTokens(
            currentAmount,
            step.minOut,
            step.path,
            address(this),
            block.timestamp
        );

        uint balanceAfter = IERC20(outputToken).balanceOf(address(this));
        uint received = balanceAfter - balanceBefore;

        require(received >= step.minOut, "Slippage too high");

        currentToken = outputToken;
        currentAmount = received;
    }

    require(currentAmount >= minFinalOut, "Final output too low");

    require(IERC20(currentToken).transfer(owner, currentAmount), "Final transfer failed");

    return currentAmount;
}
  • Интеграция на флаш заем: Ако оптималната сума за арбитража изисква флаш заем, строителят интегрира логиката на флаш заем (заем → изпълнение на суапи → изплащане) в една единствена, неделима сделка, като използва договор по поръчка, който улеснява тази атомна операция чрез интерфейса FlashLoanSimple на Aave.
  • Ето функцията за изпълнение на договора за солидностОперация (част от по-голям договор за FlashLoanReceiver), която се нарича от Aave Pool и съдържа логиката на арбитража, използвайки заетите средства:
function startArbitrage(
      address token,
      uint256 amount,
      SwapStep[] calldata steps,
      uint256 minFinalOut
) external onlyOwner {
    bytes memory params = abi.encode(steps, minFinalOut);
    POOL.flashLoanSimple(address(this), token, amount, params, 0);
}

function executeOperation(
    address asset,
    uint256 amount,
    uint256 premium,
    address initiator,
    bytes calldata params
) external override returns (bool) {
    require(msg.sender == address(POOL), "Untrusted lender");
    require(initiator == address(this), "Unauthorized initiator");

    (SwapStep[] memory steps, uint256 minFinalOut) = abi.decode(params, (SwapStep[], uint256));

    // Execute the arbitrage
    address currentToken = asset;
    uint currentAmount = amount;

    for (uint i = 0; i < steps.length; i++) {
        SwapStep memory step = steps[i];
        require(step.path[0] == currentToken, "Path mismatch");

        address outputToken = step.path[step.path.length - 1];

        // Save balance before swap
        uint balanceBefore = IERC20(outputToken).balanceOf(address(this));

        // Safe approve
        require(IERC20(currentToken).approve(step.router, 0), "Reset approve failed");
        require(IERC20(currentToken).approve(step.router, currentAmount), "Approve failed");

        IUniswapV2Router(step.router).swapExactTokensForTokens(
            currentAmount,
            step.minOut,
            step.path,
            address(this),
            block.timestamp
        );

        uint balanceAfter = IERC20(outputToken).balanceOf(address(this));
        uint received = balanceAfter - balanceBefore;

        require(received >= step.minOut, "Slippage too high");

        currentToken = outputToken;
        currentAmount = received;
    }

    require(currentAmount >= amount + premium, "Insufficient profit");
    require(currentAmount >= minFinalOut, "Final output too low");

    // Repay the loan
    require(IERC20(asset).approve(address(POOL), amount + premium), "Approval failed");
    
    // Transfer profits to owner
    uint profit = IERC20(asset).balanceOf(address(this)) - (amount + premium);
    if (profit > 0) {
        require(IERC20(asset).transfer(owner, profit), "Profit transfer failed");
    }

    return true;
}
  • Оценка и цена на газа: Динамично оценява необходимия газ за транзакцията и определя подходяща цена на газа (или такса за приоритет за L2s като Base), за да осигури своевременно включване в блок.
  • Транзакционен дисплей: След като бъде построен, подписаната транзакция се изпраща до блокчейн възела на базата. Изборът на базата е стратегически: за разлика от Ethereum L1, настоящата архитектура на базата не се характеризира с публично видима mempool в традиционния смисъл. Това означава, че транзакциите са по-малко податливи на директен генерализиран frontrunning от ботове, сканиращи mempool. Докато Maximal Extractable Value (MEV) все още съществува на L2, механизмите за нейното извличане се различават от L1, а директният mempool sniping е значително намален, предлагайки по-предсказуема среда за изпълнение за арбитражите.
  • Асинхронна обратна връзка: След изпращане на транзакцията, услугата изпраща уведомление до Honeywall Service, за да сигнализира, че транзакцията е инициирана и изисква мониторинг.

Honeywall Service: Валидиране и сигурност след изпълнението

Honeywall Service действа като критичен проверяващ след изпълнението и надежден защитен слой за арбитражния бот.

  • Мониторинг на резултатите от транзакциите: След като строителят на транзакциите изпрати транзакция, услугата Honeywall наблюдава включването й в блок и нейния резултат.
  • Записване на печалбата: Ако сделката е успешна и генерира печалба (както се очаква от симулацията), данните за печалбата се записват за проследяване и анализ на изпълнението.
  • Анализ на неуспеха: В случай на неуспех на транзакцията, Honeywall анализира причината за реверса.
  • Honeypot/Scam Detection and Blacklisting: A key security feature is its ability to identify “honeypot” tokens or pools that implement deceptive logic (e.g., allowing buys but preventing sells, or imposing exorbitant hidden taxes on sells).
  • Външна интеграция на доставчици: Тя се интегрира с външен доставчик или база данни от известни договори за меден прашец, за да пренасочи двойките, използвани в неуспешни транзакции, като по този начин идентифицира потенциалните измами.
  • Динамичен черен списък: Ако определена двойка или пул е идентифициран като меден съд или проблематичен поради неочаквано високи данъци, той веднага се добавя към черния списък, поддържан от базата данни.
  • Интеграция на филтри на Блум: Този черен списък се управлява ефективно чрез механизъм за филтриране на Блум. Това позволява на услугата за четене на данни на блокчейн бързо да проверява новооткритите двойки срещу черния списък, преди дори да извлече резервите си или да ги добави към пазарната диаграма.

Заключение на архитектурния дизайн

Модулната, базирана на събития архитектура, внедрена в Go, съчетана със специализирани услуги за поглъщане на данни, моделиране на пазара, оптимизиране на възможностите, бързо изпълнение и стабилна сигурност, образува гръбнака на нашия високопроизводителен арбитражен бот.Този дизайн гарантира, че системата може да реагира с несравнима скорост на променливи пазарни възможности, като същевременно намалява значителните рискове, присъщи на DeFi „Тъмна гора“.

Откриване на възможности и оптимално изпълнение: мозъкът на бота

Истинската интелигентност на арбитражния бот се крие в способността му бързо и точно да идентифицира печелившите възможности в един постоянно променящ се пазар и след това да оптимизира изпълнението за максимална възвръщаемост.

Моделиране на пазара на DeFi като график

Както е представено в архитектурния преглед, нашата услуга Market Graph представя DeFi пейзажа като насочена диаграма.nodes, докато полюсите за ликвидност на различни децентрализирани борси (DEX) действат катоedgesТеглото на всеки ръб представлява разходите за транзакции през този пул.

За ефективно откриване на възможности за арбитраж, които се проявяват като печеливши цикли, ние превръщаме проблема с намирането на печеливша последователност от сделки в намиране на рентабилен цикъл.negative cycleТази трансформация се постига чрез прилагане на логаритмична функция към обменните курсове.

Необходимостта от логаритми за откриване на цикли

The core idea behind arbitrage is to multiply a starting amount by a series of exchange rates to end up with more of the original asset. For example, if we start with A units of TokenXТърговия с него заTokenYСлед товаTokenYзаTokenZИ накраяTokenZНазад къмTokenXКрайната сума ще бъде:

Работата с продукти в графични алгоритми е трудна.Обичайна техника в изчислителните финанси за превръщане на множителни проблеми в добавителни е да се приложи логаритм.

За да имаме успешен цикъл, трябва даВ края на краищата (а)което означаваln(RateX→Y) + ln(RateY→Z) + ln(RateZ→X) > 0Въпреки това, типичните алгоритми за най-кратки пътеки (като Bellman-Ford, които използваме) са предназначени да намерят пътеки с минимумСумаЗа да направим печеливш цикъл да се появи като „негативен цикъл“ в нашия график, ние просто отричаме логаритмичните коефициенти:

ln(RateX→Y) + ln(RateY→Z) + ln(RateZ→X) > 0

С тази трансформация сумата от отрицателни тежести, която води до отрицателна стойност (т.е. отрицателен цикъл), директно показва печеливша арбитражна възможност.

Прецизност при работа сBigInt

Количеството токени в DeFi може да варира много, от малки фракции (напр. за ERC-20 токени с 18 десетични места) до много големи числа (напр. стабилни монети). Тази екстремна хетерогенност в мащаба, обхващащаща до 18 значими цифри, прави стандартната плаваща точка аритметика много податлива на грешки с точност. Такива грешки, въпреки че изглеждат малки, могат да доведат до неправилно идентифицирани възможности или, по-лошо, нерентабилни сделки.

За да преодолеем това, нашата услуга Market Graph и всъщност всички изчисления, включващи суми на токени и обменни курсове в бота, използват Go'smath/bigПакетът, в частностBigIntза аритметични цели иBigFloatза плаваща точка операции, когато е необходимо.BigFloatпредлага произволна прецизност, прилагайкиlogдвеBigIntилиBigFloatстойности изисква внимателна обработка, като стандартmath.LogФункции, които работят на nativefloat64Тук са необходими персонализирани имплементации или външни библиотеки, способни на логаритми с произволна точност.

func getLogRate(reserve0, reserve1 *big.Int) *big.Float {
	const prec = 1024
	resIn := new(big.Float).SetPrec(prec).SetInt(reserve0)
	resOut := new(big.Float).SetPrec(prec).SetInt(reserve1)

	// Effective Rate
	rate := new(big.Float).SetPrec(prec).Quo(resOut, resIn)
	logRate := bigfloat.Log(rate)

	return logRate.Neg(logRate)
}

Алгоритъмът на Bellman-Ford

След като пазарът DeFi е точно моделиран като график с логаритмични отрицателни тежести на ръба, задачата за намиране на възможности за арбитраж се свежда до идентифициранеnegative cyclesЗа тази цел, ние използваме тозиBellman-Ford algorithm.

Наречен на името на Ричард Белман и Лестър Форд младши, Bellman-Ford е универсален алгоритъм за най-кратки пътища, способен да обработва графики с отрицателни тежести на ръба. За разлика от алгоритъма на Dijkstra, който се проваля в присъствието на отрицателни цикли, Bellman-Ford е специално проектиран да ги открие.

Алгоритъмът работи чрез итеративно отпускане на ръбовете, постепенно намиране на по-къси пътища до всички възли от един източник. Ако, след итерации ÁthaV Átha−1 (където ÁthaV Átha е броят на върховете), допълнителна N-ти итерация намира път, който все още може да бъде "отпуснат" (т.е. може да се намери по-кратък път), това показва наличието на отрицателен цикъл.


type Edge struct {
	Pair     string
	From     Token
	To       Token
	LogRate  *big.Float
	Reserve0 *big.Int
	Reserve1 *big.Int
	Dex      string
	MinOut   *big.Int
}

type Graph struct {
	nodes         map[string]Token
	Edges         map[string][]*Edge
	pairChan      *chan GraphMessage
	dexCheckChan  *chan DexDexMessage
	subscriptions []*chan time.Duration
	mu            sync.RWMutex
}

// Bellman-Ford algorithm to find arbitrage cycles
func (g *Graph) FindArbitrage(source Token) ([]*Edge, bool) {
	sourceKey := source.Address

	g.mu.RLock()
	defer g.mu.RUnlock()

	distance := make(map[string]*big.Float)
	predecessor := make(map[string]*Edge)

	// 1. Init
	for token := range g.nodes {
		distance[token] = new(big.Float).SetInf(false)
	}
	distance[sourceKey] = new(big.Float).SetFloat64(0)

	// 2. Relax edges V-1 times
	for i := 0; i < len(g.nodes)-1; i++ {
		for _, edgeList := range g.Edges {
			for _, e := range edgeList {
				from := e.From.Address
				to := e.To.Address

				if !distance[from].IsInf() && new(big.Float).Add(distance[from], e.LogRate).Cmp(distance[to]) < 0 {
					distance[to].Add(distance[from], e.LogRate)
					predecessor[to] = e
				}
			}
		}
	}

	// 3. Negative cycle detection
	var cycleStartToken string
	for _, edgeList := range g.Edges {
		for _, e := range edgeList {
			from := e.From.Address
			to := e.To.Address
			if !distance[from].IsInf() && new(big.Float).Add(distance[from], e.LogRate).Cmp(distance[to]) < 0 {
				cycleStartToken = to
				break
			}
		}
		if cycleStartToken != "" {
			break
		}
	}

	if cycleStartToken == "" {
		return nil, false // No Arbitrage
	}

	// 4. detect first cycle node
	visited := make(map[string]bool)
	current := cycleStartToken
	for !visited[current] {
		visited[current] = true
		edge := predecessor[current]
		if edge == nil {
			return nil, false // missing edge
		}
		current = edge.From.Address
	}

	// 5. Complete cycle
	cycleStart := current
	cycle := []*Edge{}
	for {
		edge := predecessor[current]
		if edge == nil {
			return nil, false // missing edge
		}
		cycle = append(cycle, edge)
		current = edge.From.Address
		if current == cycleStart {
			break
		}
	}

	// 6. Invert cycle
	for i, j := 0, len(cycle)-1; i < j; i, j = i+1, j-1 {
		cycle[i], cycle[j] = cycle[j], cycle[i]
	}

	return cycle, true
}

Изчисляване на оптимален размер на входа: максимизиране на печалбата

След като се идентифицира отрицателен цикъл (възможност за арбитраж), следващата критична стъпка е да се определиoptimal input amount (dx) for the initial trade in the sequence. This is not arbitrary; the profitability of an arbitrage opportunity is a non-linear function of the trade size due to the inherent slippage and fees associated with AMM swaps.

As detailed in “An analysis of Uniswap markets”, the constant product formula inherently implies a convexity in the relationship between input and output amounts. Specifically, as the trade size increases, the effective exchange rate worsens due to the pool’s invariant. This means there’s a sweet spot: too small an amount might not cover gas fees, while too large an amount might incur excessive slippage, eroding profits.

Проблемът с максимизирането на печалбата еconvex optimization problemЗа поредица от N swaps в арбитражен път, крайната сума на изхода (и следователно печалбата) може да бъде изразена като функция на първоначалния размер на входа (dx ). Докато точното аналитично решение за многократния арбитраж може да бъде сложно, особено с различните структури на таксите и кривите на плъзгане в различни AMMs, функцията, представляваща печалбата минус разходите (включително газ) обикновено е изпъкнала.

Нашата услуга за арбитражна стратегия се справя с това, като използва решение за оптимизация от Go's.gonum/optimizeТози разпределител взема функция, представляваща нетната печалба (печалба от суапи минус прогнозни такси за газ и всякакви премии за флаш заем) и намира входната сума, която максимизира тази стойност.amountOutФормулатаdy = (x + dx) / (dx⋅ y)за всеки етап от пътя на арбитража, отчитане на междинните резерви, таксите и отклоненията на всеки етап.

func getOptimalAmoutIn(edges []*Edge, decimals int) (*float64, error) {
	factor := math.Pow10(decimals)
	intMax, _ := constants.GetRouterReserveFromToken(edges[0].From.Address)

	maxCapital := new(big.Float).Mul(new(big.Float).SetInt64(intMax), big.NewFloat(factor))
	fee := big.NewFloat(0.997)

	problem := optimize.Problem{
		Func: func(x []float64) float64 {
			delta := big.NewFloat(x[0])
			if delta.Cmp(big.NewFloat(0)) < 0 || delta.Cmp(maxCapital) > 0 {
				return math.Inf(1)
			}

			delta_i := new(big.Float).Set(delta)
			for _, edge := range edges {
				effectiveIn := new(big.Float).Mul(delta_i, fee)
				reserveIn := new(big.Float).SetInt(edge.Reserve0)
				reserveOut := new(big.Float).SetInt(edge.Reserve1)

				num := new(big.Float).Mul(reserveOut, effectiveIn)
				denom := new(big.Float).Add(reserveIn, effectiveIn)
				delta_i = new(big.Float).Quo(num, denom)
			}

			profit := new(big.Float).Sub(delta_i, delta)
			result, _ := profit.Float64()
			return -result
		},
	}

	result, err := optimize.Minimize(problem, []float64{1.0}, nil, nil)
	if err != nil {
		return nil, err
	}

	return &result.X[0], nil
}

Симулация на суапове и оценка на рентабилността

Преди всяка транзакция да бъде изпратена, Арбитражната стратегия извършва внимателнаsimulated executionТази стъпка е от решаващо значение за проверка на реалната рентабилност, като се имат предвид пазарните условия в реално време и точните параметри на предложената търговия.

Симулацията използва текущите резерви на участващите ликвидни басейни и изчислената оптимална сума на входа.За всяка стъпка в многократния път се прилага специфичната формула на AMM (например формулата на постоянния продукт за Uniswap V2-подобни басейни) за изчисляване на очаквания изход:

func (ab *ArbitrageBuilderV2) calculateProfitabilityWithSlippage(edges []*Edge, decimals int) (*big.Float, *big.Float, error) {
	opt, err := getOptimalAmoutIn(edges, decimals)
	if err != nil {
		return nil, nil, err
	}
	optBig := new(big.Float).SetFloat64(*opt)
	amount := new(big.Float).Set(optBig)

	fee := big.NewFloat(0.997)

	for _, edge := range edges {
		if edge.Reserve0 == nil || edge.Reserve1 == nil ||
			edge.Reserve0.Cmp(big.NewInt(0)) == 0 || edge.Reserve1.Cmp(big.NewInt(0)) == 0 {
			return nil, nil, errors.New("edge has invalid reserves")
		}

		reserveIn := new(big.Float).SetInt(edge.Reserve0)
		reserveOut := new(big.Float).SetInt(edge.Reserve1)

		amountInWithFee := new(big.Float).Mul(amount, fee)
		if amountInWithFee.Cmp(reserveIn) >= 0 {
			return big.NewFloat(-1.0), nil, errors.New("amount exceeds available reserves")
		}

		// "x * y = k"
		numerator := new(big.Float).Mul(reserveOut, amountInWithFee)
		denominator := new(big.Float).Add(reserveIn, amountInWithFee)
		amountOut := new(big.Float).Quo(numerator, denominator)

		amount = amountOut
	}

	profit := new(big.Float).Sub(amount, optBig)
	profit.Sub(profit, ab.EstimateGasCost(len(edges)))
	profit.Sub(profit, new(big.Float).Mul(optBig, big.NewFloat(0.005)))

	normalizedProfit := new(big.Float).Quo(profit, new(big.Float).SetFloat64(math.Pow10(decimals)))
	return normalizedProfit, optBig, nil
}

В допълнение, симулацията включваminimum output amount (minOut)Проверка на всеки един от тези етапиminOutстойностите се извличат от симулираните очаквани изходи и се задават като параметри в реалната транзакция на веригата.Ако поради мрежова латентност, предна линия или неочаквани пазарни условия реалната възвръщаемост на суапа на веригата е по-малка от посоченатаminOutТози механизъм е жизненоважна предпазна мярка, която предотвратява бота да завърши нерентабилна последователност от сделки и ограничава загубите само до газа, изразходван за обратната сделка.

Само ако крайната нетна печалба, след всички такси, свлачища, разходи за газ и премии за флаш заеми, надвишава предварително определена стойност.profit threshold (e.g., 0.5% of the initial input amount) is the opportunity deemed viable and passed to the Transaction Builder Service for execution. This threshold ensures that the bot only pursues opportunities with a significant enough margin to warrant the computational and on-chain costs.

Транзакционно инженерство: Бързо изпълнение в тъмната гора

Идентифицирането на печеливша арбитражна възможност е само половината от битката; другата, може би по-критична, половина се крие в способността да се изпълнява търговията с несравнима скорост и надеждност.В хипер-конкурентната „Тъмна гора“ на DeFi, където възможностите са мимолетни и усъвършенствани ботове живеят за всяка милисекунда, транзакционното инженерство се превръща в художествена форма.Transaction Builder Service designed to ensure lightning-fast and secure execution.

Императивът на скоростта

Прозорецът за рентабилност на арбитражните възможности на децентрализираните борси често се измерва в милисекунди. Разликите в цените бързо се откриват и експлоатират от много автоматизирани системи, което създава ожесточена надпревара да бъдеш първият, който да включи рентабилна транзакция в нов блок. Всяко забавяне, колкото и незначително да е, може да доведе до възможността да бъде уловена от конкурент, което води до неуспешна транзакция и изразходвани такси за газ. Следователно всяко решение за проектиране в услугата Transaction Builder е насочено към свеждане до минимум на закъснението на всеки възможен етап, от изграждането на транзакцията до подаването на мрежата.

Оптимизация на паметта за изграждане на незабавни транзакции

To achieve the necessary velocity, our system prioritizes having all essential transaction components readily available in memory, eliminating costly I/O operations or on-chain calls during the critical transaction building phase.

  • Вместо да анализираме определенията на ABI и функцията за кодиране за всяка транзакция, нашата система предварително анализира и опакова необходимите структури от данни на ABI и селекторите на функции в масиви от сурови байтове. Тези предварително изчислени байтови последователности за общи контрактни взаимодействия (напр. swapExactTokensForTokens, flashLoanSimple, transferFrom) се съхраняват в паметта. Когато се идентифицира възможност за арбитраж, Transaction Builder може бързо да събере данните за обажданията, като просто съедини тези предварително опаковани компоненти със специфичните за търговията параметри, което значително намалява времето за обработка.
  • За да се избегнат излишни повиквания на веригата за транзакционни метаданни, специална структура на помощната програма в бота поддържа критични, често актуализирани стойности в паметта:
  • Несъответствие на сметката: Несъответствието (броят на транзакциите, изпратени от адрес) е от решаващо значение за предотвратяване на повторни атаки и осигуряване на поръчка на транзакцията.Той се извлича веднъж и след това се управлява постепенно в паметта, с надеждна обработка на грешки, за да се синхронизира отново, ако транзакцията се провали или неочаквано е включена извън реда.
  • Оптимални газови параметри: Вместо да търси в мрежата цените на газа (или базовите такси / приоритетните такси на веригите EIP-1559) за всяка транзакция, ботът периодично извлича оптимални газови параметри.
  • Информация за подписващия: Частният ключ на портфейла на бота и свързания с него подписващ обект (използвани за криптографско подписване на транзакции) се зареждат в паметта при инициализиране.

Чрез запазване на тези жизненоважни компоненти в паметта, Transaction Builder Service може да конструира и подпише пълна blockchain транзакция само за микросекунди, готови за незабавно изпращане.

Динамичен избор на интелигентни договори: Флаш заеми срещу директни суапи

Службата за арбитражна стратегия предава оптимизиран арбитражен път и изчислената оптимална сума за вход на строителя на транзакциите.amountInи независимо дали превишава предварително определен праг на капитала (или ако стратегията изрично го изисква), Transaction Builder динамично избира между два основни интелигентни договора за изпълнение:

  • Договор за изпълнение на директен суап: За възможности, които могат да бъдат финансирани директно от собствения капитал на бота, строителят използва функцията executeArb (или подобна) на персонализиран мултисвап прокси договор.Както е показано в глава 3, този договор взема входните токени от портфейла на бота и изпълнява цялата последователност от суапи в рамките на една, атомна транзакция.
  • Интегриран договор за флаш заем: Когато изчислената оптимална сума за арбитраж е значително по-голяма от наличния капитал на бота, строителят насочва отделен, персонализиран интелигентен договор, предназначен да инициира и управлява флаш заеми. Функцията за стартиране на този договорArbitrage (както е подробно описано в глава 3) изисква флаш заем от протокол като Aave, който след това извиква обратно изпълнението на договораOperation функция. В рамките на изпълнениетоOperation, цялата арбитражна последователност се извършва с помощта на заетите средства и флаш заемът (плюс малка премия) се изплаща – всичко това в рамките на тази една, атомна blockchain транзакция. Това позволява на бота да се възползва от

Този динамичен подбор гарантира ефективно разпределение на капитала и оптимално изпълнение на стратегията въз основа на спецификата на всяка открита възможност.

Mempool Dynamics: Навигация Ethereum L1 срещу Layer 2 вериги

Критичен аспект на арбитражното изпълнение е разбирането на механизма за разпространение на транзакциите на blockchain, по-специално наmempool.

  • Ethereum L1 Mempool: On Ethereum’s Layer 1, the mempool is a public, transparent waiting room for all pending transactions. Transactions broadcasted by users or bots are relayed to various nodes across the network, becoming visible to anyone monitoring the mempool. This transparency is the breeding ground for generalized frontrunning bots (often referred to as “searchers” or “MEV bots”). These sophisticated entities continuously scan the mempool for profitable transactions (e.g., large swaps that cause significant price impact, liquidations, or other arbitrage attempts). Upon detecting such a transaction, they quickly construct an identical or similar transaction, replace the original recipient address with their own, and submit it with a higher gas price (or higher priority fee in EIP-1559) to ensure their transaction is included in the block before the original, thereby stealing the profit. This competitive landscape makes direct arbitrage on L1 highly challenging without leveraging specialized MEV relays.

  • Layer 2 (L2) Chains and Reduced Mempool Visibility (e.g., Base): Our bot strategically operates on Base, an EVM-compatible Layer 2 blockchain. The architecture of many L2s, including Base, fundamentally alters the traditional L1 mempool dynamic. Base does not currently expose a publicly visible mempool in the same manner as Ethereum Layer 1. Instead, transactions are typically sent directly to a centralized sequencer or a private mempool before being batched and committed to the L1.

    This architectural difference significantly reduces the direct threat of generalized frontrunning. While MEV still exists on L2s (e.g., through sequencer-controlled ordering or other means), the immediate, public visibility of pending transactions that enables L1 frontrunning is largely absent. This provides a more predictable and secure execution environment for our arbitrage transactions, as the bot’s crafted atomic operations are less likely to be “sniped” before they even reach a block producer. This improved execution predictability contributes directly to higher success rates for profitable arbitrages.

Скорост и сигурност на възлите: основата на надеждното изпълнение

Връзката с блокчейн възела е единствената точка за влизане и излизане за всички данни и транзакции.

  • Високопроизводителна връзка с възел: Услугата за изграждане на транзакции се свързва с специализиран, високопроизводителен доставчик на възел (напр. Alchemy, Infura или самостоятелно хостван възел). Бърза връзка с ниска латентност е от съществено значение, за да се сведе до минимум времето между подписването на транзакция и нейното разпространение в мрежата.
  • Безопасността и целостта на възела: Безопасността на свързания възел е също толкова важна. Използването на надеждни доставчици на възел или осигуряването на високосигурен самостоятелно хостван възел е от решаващо значение за предотвратяване на атаки на човек в средата или манипулиране на данни. Компрометиран възел може потенциално да изтича частни ключове, да инжектира злонамерени транзакции или да манипулира данни, което води до катастрофални загуби.

Чрез внимателно оптимизиране за скорост на всеки слой, от структури за данни в паметта и предварително изчисление до стратегически подбор на веригата и надеждна инфраструктура за възли, нашият арбитражен бот е предназначен да надмине конкурентите и безопасно да се възползва от нестабилните възможности в пейзажа на DeFi.

Навигация в тъмната гора: предизвикателства, етика и бъдещи перспективи

Изграждането и експлоатацията на арбитражен бот в DeFi "Тъмна гора" е доказателство за силата на децентрализираните технологии, но също така излага на светлина значителни предизвикателства и етични съображения.

Постоянната битка срещу злонамерените актьори: Ролята на Блум

Първоначалният оптимизъм около неразрешената природа на DeFi, за съжаление, е бил смекчен от разпространението на злонамерени актьори.Honeywall ServiceТова е жизненоважна последна линия на защита, но находчивостта на тези зли актьори непрекъснато изисква да се развиват контрамерки.

Ключов елемент в тази защита еBloom filterБлум филтър е структура на вероятностните данни, която може бързо и ефективно да тества дали даден елемент е член на набор. Той е високо пространствено ефективен, но носи малка вероятност от "фалшиви положителни" (което показва, че елементът е в набора, когато не е), въпреки че никога не "фалшиви отрицателни". В нашия контекст, Блум филтърът се използва за предварително филтриране на входящи данни за събития от услугата за четене на данни на Blockchain. Той съдържа хаши на известни зловредни или високи данъчни парични адреси. Преди всякаква подробна обработка или резервно събиране, бърза проверка срещу филтъра на Блум може незабавно да изхвърли известни проблемни двойки, предотвратявайки

Въпреки сложните предварителни проверки, въведени в нашия обичайArbHelperMapУмният договор (по-специално_checkTaxLimitлогика, която симулира обиколен обмен за оценка на данъците), някои злонамерени двойки все още успяват да заобиколят тези първоначални потвърждения на веригата.getAmountsOutФункция (използвана за ценови заявки) за връщане на привидно нормални, ниско данъчни изходи.swapExactTokensForTokensили в основатаtransferТези функции могат да наложат прекомерни скрити данъци (напр. 99%) върху продажбите или дори напълно да ограничат продажбите, ефективно улавяйки средства.

По време на нашата тестова фаза се натъкнахме на значителен брой такива измамни двойки. аз лично събрах някои двойки адреси, които успешно преминаха първоначалнияgetAmountsOutПроверки, но разкрити скрити данъци или ограничения за продажба само по време на действителна (симулирана или обърната) транзакция в локална база данни. Този db файл ще бъде направен публично достъпен в GitHub хранилището на проекта, като служи като ресурс на общността, за да помогне на другите да избегнат тези капани.

Етичните последици и сянката на тъмната гора

Аналогията "Тъмна гора" е подходяща не само за конкуренцията между ботове, но и за по-широкия етичен пейзаж на DeFi.Ефективността на арбитража, въпреки че е от решаващо значение за здравето на пазара и откриването на цените, идва със силна реалност: печалбите, генерирани от арбитрите, често представляват стойност, извлечена от по-малко сложни участници на пазара.

Постоянната култура наFOMO (Fear Of Missing Out), съчетано с обща липса на разбиране на основните блокчейн механизми и финансови инструменти, прави много потребители на дребно лесно плячка в тази среда.Те навлизат в силно нестабилни пазари, взаимодействат с нови протоколи и изпълняват сделки без пълно осъзнаване на концепции като спускане, MEV или скрити договорни данъци.

Тази динамика, макар и икономически логична за тези с усъвършенствани инструменти, хвърля сянка върху репутацията на децентрализираните технологии. Разказът може бързо да премине от „финансово овластяване“ към „измамно поведение“, подкопавайки доверието в пространство, което в противен случай държи огромно обещание. DeFi, в основата си, има за цел да демократизира финансите, предлагайки неразрешен достъп и прозрачност. Въпреки това, сложният характер на MEV и разпространението на измами могат неволно да подкопаят тези идеали, създавайки двустепенна система, където само технологично опитни могат наистина да се движат безопасно. Наложително е, като строители, да признаем тези етични измерения и да се застъп

Заключение: Все още плувайки в тъмната гора

Въпреки присъщата сложност и постоянните предизвикателства на DeFi пейзажа, пътуването на инженеринга на този арбитражен бот е забележително валидиране на теоретични принципи, които отговарят на практическото изпълнение.speed, precision, and data-driven insights, способни да откриват и изпълняват многократни арбитражни възможности.

Първоначално общо очакване в рамките на "Тъмна гора" беше, че по-голямата част от арбитражната стойност ще бъде незабавно прехваната от големи, добре оборудвани играчи, като се възползват от самостоятелно хоствани възли и директен достъп до производителите на блокове.

Докато рентабилното арбитраж по по-стари модели на AMM като Uniswap V2 (които се основават главно на постоянни продуктови басейни) може да бъде предизвикателство за поддържане в дългосрочен план поради ескалирането на разходите за газ и засилената конкуренция, „Тъмната гора“ продължава да се развива. По-новите внедрения, като например концентрираните ликвидни AMM на Uniswap V3 (CLAMMs), въвеждат нови арбитражни вектори, които изискват по-сложно моделиране, но често генерират по-високи доходи поради повишена капиталова ефективност. Освен това, нарастващото поле на кръстосаното арбитраж, оползотворяването на мостове и междублоковите комуникационни протоколи, представлява по-голяма

Така че, докато все още съм беден, мога с увереност да кажа, че съм станал отличен горски навигатор.My compass is sharper, my map more detailed, and I understand the whispers of the canopy.

Репозиторията на проекта

За тези, които се стремят да се потопят по-дълбоко в практическото изпълнение и много реалните данни зад някои от "залозите", които обсъдихме, са на разположение санитизирана версия на нашата кодова база и база данни, населена с известни злонамерени двойки токени.Репозитории на GitHubТези 85 специфични двойки, макар и числено малки, генерират непропорционално значителен обем транзакции, тъй като те непрекъснато се опитват да привличат наивни ботове в нерентабилни сделки.

Репозитории на GitHub

Референции

  • Дан Робинсън, Георгиос Константопулос. „Етериумът е тъмна гора“.
  • Guillermo Angeris, Hsien-Tang Kao, Rei Chiang, Charlie Noyes и Tarun Chitra. „Анализ на пазарите на Uniswap“, Cryptoeconomic Systems.
  • Клаудио Гебия. „Анализ и внедряване на арбитражни ботове в централизираното и децентрализираното финансиране“, Университет на Цюрих.
  • Y. Zhang, Z. Li, T. Yan, Q. Liu, N. Vallarano и C. J. Tessone, “Максимализиране на печалбата в арбитражните кръгове”.


L O A D I N G
. . . comments & more!

About Author

Simone Convertini HackerNoon profile picture
Simone Convertini@SiCo
Software Engineer. I'm amazed by the technology and the value that it can bring to the world.

ЗАКАЧВАЙТЕ ЕТИКЕТИ

ТАЗИ СТАТИЯ Е ПРЕДСТАВЕНА В...

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks