Dex arbitrage

Dex arbitrage


Мультивызов

Multicall позволяет выполнять несколько запросов (вызовов) только для чтения к одному смарт-контракту, используя один запрос на узле. Это имеет три преимущества:

  • Вызовы сгруппированы вместе, поэтому вы используете только один eth_call на узле для каждого пакетного запроса. Это избавляет вас от прожигания запросов API, если вы используете сторонний RPC и имеете ограничение скорости.
  • Поскольку все запросы отправляются и возвращаются одновременно, задержка становится менее критической. Вместо ожидания времени (даже при условии распаралелливания процессов) каждого вызова вы только ждете один вызов (при условии, что многократный вызов возвращается за то же время, что и один запрос).
  • Все запросы от группового вызова возвращаются из того же блока. Это устраняет ошибки, вызванные изменением данных в нескольких блоках по мере возврата отдельных вызовов.

Теория графов в построении арбитражных путей

Вы можете прочитать все о теории графов в Википедии , но вот краткая версия:

Граф — это структура данных, состоящая из объектов и взаимосвязей между этими объектами. Узел (также называемый вершиной или точкой) — это атомарный «кусок» графа. Все узлы, имеющие отношения с другим узлом, связаны посредством ребра (также называемого ссылкой), которое может содержать произвольное количество дополнительной информации.

Пример графа

Используя приведенный выше пример, представьте, что каждый узел представляет определенный токен ERC-20. Токены ERC-20 уникальны, как и каждый узел в графе. Для каждых двух токенов, которые имеют общий пул ликвидности, можно нарисовать ребро. Оттуда перемещаемся по графу (так называемый «обход»), чтобы обнаружить возможные арбитражные пути между токенами, отслеживая, какие ребра вы посетили.

Для тестирования некоторых моментов кода помимо сети BSC я так же использую Avalanche (она так же эфир-совместима, но полная нода этой сети не требует производительного сервера за много $$, поэтому некоторые вещи я обкатываю изначально там). Поэтому следующий пример мы рассмотрим на сети Avalanche. Все наработки аналогичны и для BSC.

Давайте визуализируем простой треугольный арбитраж: начнем с некоторого количества WAVAX (узел № 0), замените WAVAX на MIM (узел № 1), замените MIM на USDT (узел № 3), затем замените MIM обратно на WAVAX (возврат к узлу № 2).

Граф, в котором узлы это токены, а ребра это LP или пара на бирже между этими токенами

В Python есть замечательный модуль NetworkX, предоставляющий набор функций и алгоритмов, предназначенных для упрощения анализа графа.

Я покажу пример того, как использовать NetworkX для построения и извлечения данных из графика токенов/LP, а затем разработать способ использования этих данных CSV для определения реальных путей арбитража в Avalanche

Немного изменим наш граф, добавив в него еще несколько ребер, поскольку пулы ликвидности между USDT и USDC и другими токенами графа так же существуют.

Дополненный граф

Теперь вы можете увидеть четыре очевидных пути, начинающихся и заканчивающихся в WAVAX:

  • WAVAX → USDC → USDT → WAVAX
  • WAVAX → USDC → MIM → WAVAX
  • WAVAX → MIM → USDC → WAVAX
  • WAVAX → USDT → USDC → WAVAX

И две подлые более длинные петли:

  • WAVAX → USDC → USDT → MIM → WAVAX
  • WAVAX → MIM → USDC → USDT → WAVAX

Эти пути в теории графов называются циклами . Цикл — это любой путь (некоторый маршрут между узлами), который начинается и заканчивается в одном и том же узле и не повторяет ребро.

Алгоритм nx.simple_cycles()позволяет нам найти все простые циклы (один и тот же начальный и конечный узел, без повторяющихся ребер) для графа.

Таким образом, спарсив все токены на нескольких различных DEX и загрузив их в python скрипт для построения масштабного графа, мы увидим что WAVAX связан с 15 035 другими токенами на трех DEX.

Используя технологию мультивызова, описанную выше, мы можем опрашивать все найденные пулы одним вызовом (не тратя запросы) на предмет изменения цены. NetworkX так же позволяет закодировать некоторые функции в ребро графа. Зашьем туда отклонение цены на заданный процент на любом из путей (используя пакетные транзакции мы можем выбрать путь любой длинны, т.к. вся сделка проводится в одной транзакции с единичной оплатой за газ) и .

Таким образом мы получим массив данных о состоянии

Используя гипотетическое уравнение:

P(x) = y_b(x) - y_a(x)

где y_b(x)— выход токена x, обмениваемого на токен y через пул B, y_a(x)— требуемая выплата в токене y для мгновенного заимствования токена x через пул A, и P(x)— разница (прибыль).

Мы знаем, что y_a(x)это можно решить с помощью библиотечной функции Uniswap getAmountIn()и y_b(x)решить с помощью getAmountOut().

Таким образом, записанный по-другому, Profit = getAmountOut(x)_b - getAmountIn(x)_axпредставляет собой количество токена x, заимствованного из пула A. Поскольку сумма, заимствованная из пула A, и сумма, переведенная в пул B, одинакова, мы можем использовать xсаму по себе вместо x_aи x_b.

Так же добавим их к ребрам графа и запустим мониторинг цены с задержкой появления нового блока.

Распараллелив процессы подсчета количества входных и выходных токенов для предполагаемой суммы арбитража и данные о ценах, мы получим сигнал о выгодности проведения арбитража по данному пути и отошлем этот сигнал на наш смартконтракт. У бота есть очень конкретная цель: следить за состояниями блокчейна и выполнять соответствующий вызов контракта всякий раз, когда он видит выгодную возможность. В основном у нас есть контракт, и у нас есть прочная основа для бота, который может просто вызвать арбитраж вместо обмена по старинке.






Report Page