January 5, 2023

Решение трилеммы мостов

Всем привет! С вами Тёма!

Сегодня мы будем разбираться с решением трилеммы мостов

Предисловие

Несмотря на постоянно растущую активность в дефи, до сих пор не существует адекватного решения для переноса нативных токенов между сетями

Существующие мосты имеют три основные проблемы:

  1. Они полагаются на обёрнутые или токены-посредники
  2. Они могут поддерживать только небольшое кол-во сетей
  3. Они не могут взаимодействовать со смарт контрактами в сети назначения (куда переводятся средства)

Wrapped или токены-посредники требуют дополнительного свапа в сети назначения для того, чтобы получить нативный токен, это создаёт две проблемы: дополнительные затраты на газ и допополнительная трата времени на свап вручную (а значит не самый лучший user experience)

Поэтому ребята из LayerZero создали Дельта(Δ)-алгоритм, который предлагает использовать кроссчейн-ликвидность, следовательно кроссчейн-мост, который работает исключительно с нативными токенами и при этом гарантирует завершённость транзакций

Подробнее

Обычно мосты встречаются с проблемой трилеммы, где они должны исключить одно из следующего:

  1. Мгновенная гарантированная завершённость
  2. Единая ликвидность
  3. Транзакции с использованием нативных токенов

Обычно существующие мосты пренебрегают третьим пунктом, делая выбор в пользу схемы "залочил-заминтил", где они лочат нативный токен в чейне-отправителе, и потом минтят обёрточный токен в чейне-получателе. Это ведёт к проблемам, которые указаны выше

На спасение приходит LayerZero, который предлагает Δ-алгоритм, объединяя ликвидность не жертвуя гарантированной завершённостью транзакций. Теперь есть единая ликвидность, удобная как для провайдеров ликвидности (которым теперь не нужно переносить токены в чейн-получатель, предоставляя нативные токены только одного блокчейна, при этом получая комиссию со всех входящих транзакций несмотря на то, каким будет чейн-отправитель), также удобная и для пользователей (которым не нужно дополнительно платить комиссию за свап обёрточных токенов)

Мгновенная гарантированная завершённость

Многие мосты используют схему "залочил-заминтил", что приводит к теоретически возможной неограниченной ликвидности в чейне-получателе, однако именно такая схема гарантирует завершённость транзакции. Очень важно предлагать гарантию завершённости, ведь в противном случае придётся заплатить комиссию за ревёрт(отмену/возврат) транзакции. В таких случаях мост должен:

  1. предоставлять пользователю возможность вручную отменить транзакцию
  2. авансом запросить достаточное кол-во газа для отмены
  3. самостоятельно оплачивать отмену

В целом это не очень хорошо

Ещё есть пример AnySwap (гарантирющий завершённость), который минтит $ANY в чейне-получателе, опять таки приводя к надобности обменять $ANY в конечном чейне

Δ-мосты решают эту проблему

Кроссчейн компонуемость

На данный момент обычные мосты могут предложить только компонуемость внутри чейна-отправителя, то есть можно взаимодействовать с другими смарт-контрактами только внутри чейна-отправителя, а в получателе — нет. Δ-мосты позволяют взаимодействовать с контрактами на обоих концах. Например, мы можем сделать следующее: свапнуть актив внутри чейна-отправителя, потом полученный нативный токен перевести в нативный токен чейна-получателя, и там ещё раз свапнуть на требуемый актив. И это всё внутри одной транзакции

Единая ликвидность

Проблема обычных мостов такова, что когда мы хотим добавить к мосту новый чейн, приходится добавлять ликвидность в каждый другой чейн, который подключён к мосту. Это всё из-за "разделённой" ликвидности, где в каждом блокчейне должна быть отдельная ликвидность. Δ предлагает объединить всё в одно целое

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

Дизайн алгоритма

Давайте ещё раз представим нашу кроссчейн ликвидность. В такой модели каждый блокчейн держит свою отдельную ликвидность (в нативном токене), при этом она неявно разделена на части, отведённые на каждый другой блокчейн, включённый в работу моста

Дельта(Δ) неявно разделяет объединённую ликвидность между отдельными блокчейнами, давая возможность Δмосту использовать объединённую ликвидность без ущерба гарантии завершённости

То есть имея средства в чейне Х на сумму $100, пул выделяет запас в $50 чейну Y и $50 чейну Z. Основная идея в том, чтобы предоставить возможность занимать/возвращать ликвидность между этими неявно разделёнными частями, если исключена возможность превышения кредита, позволяя Δ-алгоритму сохранять эти части в состоянии баланса несмотря на несбалансированный объём транзакций. Каждая часть представляет собой пропускную способность, доступную на однонаправленном канале, соединяющая чейн Y или чейн Z с чейном X, и мы говорим, что канал находится в дефиците, если его пропускная способность падает ниже исходного значения, и или в избытке, если пропускная способность выше исходного значения

Трансфер (бридж токенов) состоит из депозита в чейне-отправителе и соответствующего вывода в чейне-получателе

При получении запроса на трансфер из чейна X в чейн Y, Δ-алгоритм будет следовать правилам:

  1. Если любой канал в чейне X находится в дефиците — распределить все/часть только что внесённых средств на закрытие дефицита
  2. Любые оставшиеся средства после закрытия всех дефицитов распределяются среди всех каналов соответственно весу (о котором далее)

Также Δ-алгоритм отслеживает все транзакции в локальном файле credits, которые затем по возможности вставляются в транзакции пользователей для того, чтобы чейн был в курсе запаса пропускной способности во всех каналах (к другим чейнам). Это делается для того, чтобы баланс(не актив) никогда не превышал действительную пропускную способность. Это также гарантирует завершённость транзакции

Δ-алгоритм требует хранения этих данных на каждом чейне. S - это чейн-отправитель, D - это чейн-получатель. (Source chain & Destination chain)
Вспоминаем про аллокации, которые пул выделяет под каждый другой чейн (неявное деление пула)

Обозначения

Weight, например, изменяется тогда, когда добавляются другие блокчейны, weight также задаётся при изначальной конфигурации, они необязательно должны быть таким же, как на картинке

Великий и ужасный Δ-алгоритм

Его задача содержать всё в гармонии:

  • все балансы должны быль >= от их изначального значения
  • все балансы должны быть пропорциональны относящимся к ним пулам ликвидности (актив=сумма_балансов)

Но самое главное — выполнять условие:

Псевдокод:

Чейн-отправитель S начинает алгоритм тогда, когда получает запрос от пользователя на перевод t единиц ликвидности в чейн D. Сначала проверяется, достаточно ли средств в чейне D для проведения трансфера, отклоняя транзакцию если баланс между S и D меньше, чем размер трансфера t (строчки 1-3). Проверив, что баланс достаточен, мы обновляем активы (a 's) и баланс (b 's,d) чтобы отразить депозит пользователя и его намерение вывести из чейна D, соответственно (строчки 4-5)

После обновления балансов и активов, основной алгоритм начинается со строчки 6. Количество diff 's,x рассчитано для каждого удалённого (дистанцированного) чейна X, к которому подключён чейн S (строчки 6-8). Активы в количестве diff 's,x должны быть выделены чейну X для его возвращения к исходному балансу. То есть, diff 's,x — это разница между целевым и текущим балансами на удалённом чейне X. Функция max() предназначена для того, чтобы diff 's,x не был отрицательным. Интуитивно можно понять, что здесь мы считаем, достаточно ли у каждого подключённого чейна X к чейну S баланса для проведения транзакции. Если баланса мало, то Δ перераспределяет некоторое кол-во активов в попытке восстановить баланс X, базируясь на LP чейна S, и соответствующего веса для X. Баланс удалённого чейна X равен сумме последнего известного баланса X и долгов чейну X. Это не обязательно будет отражать текущий баланс b 'x,s , поскольку долги известны только чейну S. Однако, информация о долгах всё равно будет передана чейну X благодаря прикреплению этого запроса к запросу юзера на трансфер средств

Затем мы посчитаем Total(всего), что является общим кол-вом средств, которые необходимо распределить для восстановления каждого удалённого баланса (к изначальному значению) (строка 9). Вместо прямого перераспределения активов, Δ-алгоритм выделяет часть от текущего перевода t на каждый удалённый чейн. Если t хотя бы такой же большой, как и Total, тогда текущая транзакция имеет достаточный размер для того, чтобы полностью перебалансировать все удалённые балансы. В данном случае мы суммируем значения diff и t (строчки 10-12). Если сумма для перераспределения меньше, чем текущая транзакция (т.е. Total < t), тогда строка 11 не имеет эффекта. Мы высчитываем t' , (который может быть равен 0), который равен части от t, которая остаётся после использования Total для перераспределения балансов удалённых чейнов (строка 13)

Самые важные части алгоритма — это строки 14-16. Здесь мы возвращаем долги каждому чейну в попытке восстановить удалённым балансам их первоначальные значения. Существующим кредитам по каждому отдельному чейну мы даём два значения:

  1. Сумма ребалансировки diff 's,x для данного удалённого чейна
  2. Пропорциональная сумма оставшегося баланса для перевода t' , который посчитали ранее, взвешенного в соответствии с предоставленным параметром веса w 's,x

Строка 17 — создаёт сообщение для отправки в чейн D. Мы обновляем последний известный баланс для чейна D (lkb 's,d), и потом обнуляем все долги для чейна D (строки 18-19). Наконец, чейн D уведомлён о размере перевода и непогашенных долгах (строка 20) и транзакция совершается в чейне S

Строки 21-24 описывают транзакцию в чейне-получателе, с активами блокчейна-получателя (a 's) и последним известным балансом lkb 's,d, обновленными для отражения перевода размером t

Доказательство мгновенной гарантированной завершённости

Даём пруф того что Δ-алгоритм достигает мгновенной гарантированной завершённости. Это когда мы гарантируем что трансфер, не отклонённый чейном-отправителем гарантировано завершится с успехом в чейне-получателе, опираясь на факт достаточной ликвидности в чейне-получателе. Важно отметить, что транзакции атомарны — весь код в строках 1-17 выполняется атомарно (либо выполняется полностью, либо не выполняется вовсе)

В Δ-алгоритме определили три теоремы для помощи доказательства мгновенной гарантированной завершённости:

Теорема 1

Удалённый баланс b 'd,s никогда не может превосходить последний известный баланс lkb 'd,s

Теорема 2

Сумма всех последних известных балансов (LKB) и долгов на данном чейне никогда не может превосходить локальные активы на этом чейне

Теорема 3

Недостатки

Δ имеет один недостаток: пользователи могут истощить доступный баланс для отдельного канала (пары). Для решения проблемы представляем вам уравновешенные комиссии, это комиссии за транзакцию, составленные таким образом, чтобы поощрять пользователей за переводы ликвидности, способствующие удержанию всех балансов выше их изначального значения. Основная идея заключается в том, чтобы брать дополнительную комиссию с пользователей тогда, когда они переводят средства с чейна-отправителя (S) на чейн-получатель (D) при высоком lkb 'd,s и наоборот, возвращать комиссию при низком lkb 'd,s. Благодаря этому юзеры будут охотнее восполнять ликвидность

Пока конечный алгоритм не разработан, но вот простейший пример:

Примеры

Здесь показана работа Δ-алгоритма, но без работы уравновешенных комиссий

Каждая горизонтальная линия показывает одну транзакцию, при этом каждая транзакция разделена на две части для удобства демонстрации. Также для демонстрации показаны изначальное состояние чейнов до транзакций (сверху) и после (снизу)

Для каждой транзакции мы комментируем изменения в локальной среде, также в зелёном кружочке отражён номер строки (в псевдокоде выше) которая срабатывает

Исходное положение:

Все чейны находятся в равных состояниях, за небольшим исключением: чейн Y имеет веса 0.6 и 0.4 по отношению к чейнам X и Z соответственно, тогда b 'x,y равен 60, и b 'z,y равен 40. Получается чейн X может отправить только до $60 в чейн Y; а чейн Z может отправить до $40 чейну Y.

Транзакция 0, шаг 0:

Пользователь запрашивает перевод $40 от X к Y. Транзакция начинается с депозита $40 в пул ликвидности в чейне X. Поскольку сумма транзакции меньше доступных средств, транзакция не отклоняется. Далее, a 'x теперь равняется 140, и b 'x,y теперь равен 20 (согласно строкам кода 4 и 5 соответственно). Потом считают diff, Total, t' . В случае транзакции #0, все LKB находятся в изначальном положении, поэтому вся транзакция разделена между c 'x,y и с 'x,z , пропорционально к w 'x,y и w 'x,z соответственно. В результате транзакция размером 40 разделяется на 20 для чейна Y и на 20 для чейна Z (строка 15)

Транзакция 0, шаг 1:

Δ-алгоритм уведомляет чейн Y о транзакции и любых непогашенных долгах. С этой целью, мы начинаем с обновления lkb 'y,x до 70 в чейне X для отражения долгов (строка 18), а затем обнуление долгов (строка 19). После чего, мы отправляем транзакцию размером t с информацией о долгах до их обнуления (c 'x,y = 20) в чейн Y. В ответ на получение этого сообщения, чейн Y обновляет свои активы и баланс для отражения перевода активов (строки 22-23). Чейн Y теперь обновляет последнее известное значение баланса b 'x,y базируясь на полученном долге в 20 единиц (строка 24). Наконец, чейн Y может выдать юзеру $40 и совершить транзакцию, завершив процесс переноса средств через мост

Надеюсь статья была интересной и понятной!

Все мои ресурсы - https://t.me/ortomich_links