DeFi
February 26

Вводный курс DeFi для всех. Работа с dAPPs через смарт-контракты. Uniswap. Часть I

DeFi 2026

Итак, продолжаем наш бесплатный курс по DeFi:

Видео по Uniswap смарт-контрактам

В этом видео поговорим про протокол децентрализованной биржи Uniswap.

Uniswap - децентрализованный протокол обмена ассетами в EVM сетях. Он имеет несколько версий. Сейчас уже запущен протокол версии 4. Но мы в данном видео будем работать с протоколом версии 3, которые пользователи также используют, чтобы производить обмен активов или становиться провайдерами ликвидности.

Работать с протоколом будем также без его нативного веб интерфейса, используя только эксплорер контрактов. Опять же делая это на случай, если Uniswap по какой-то причине заблокирует адрес нашего кошелька или наш IP адрес на уровне интерфейсов.

Для демонстрации мы также будем использовать сеть арбитрум и arbiscan.io.

Первая операция, которую будем осуществлять - обмен ассетов.

Будем менять стейблкоины USDT на USDC. Для начала нам нужно понять, сколько можем получить токенов usdc за один usdt и можем ли мы их обменять в протоколе - есть ли такая торговая пара.

Находим в документации контракт UniswapV3Factory для сети Арбитрум. Выбираем метод чтения getPool.

Указываем ему адрес токена USDT, токена USDС. Указываем комиссии торговой пары. Она может быть разной - в Uniswap предусмотрены несколько уровней комиссии: 0,01%, 0.05%, 0.30%, 1%.

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

Методу getPool передаётся значение комиссии не 0,01, например, а 100. В документации есть описание значений комиссии и чему оно соответствует. Поэтому 100 всё равно что 0,01. Такое большое значение деноминатора используется для повышения точности вычислений. Итак, проверим, есть ли пул для нашей пары с комиссией 0,01%.

Да, есть.

Теперь проверим для уровня комиссии 0,05%. Есть пул. И для комиссии 0,3%, и для 1% есть пулы. Сами разработчики в документации отмечают, что чем более рискованные активы обмениваются, тем выше % комиссии могут устанавливать провайдеры ликвидностей для пулов торговых пар.

Итого: мы поняли, что для нашей торговой пары есть пул ликвидности с минимальной комиссией за обмен 0,01%.

Понять, сколько мы получим токена Б при обмене токена А через эксплорер не удастся.

В протоколе есть контракт Quoter с его методом quoteExactInputSingle, который можно вызвать и он вернёт рассчитанное значение токена Б.

Но эксплорер не умеет в транзакции (quoteExactInputSingle - метод записи) показать значение, которое возвращает метод. Можно писать скрипты используя различные фреймворки, например, Foundry, Brownie и в них делать вызов этого метода. Но это требует квалификации программирования. Поэтому мы будем сразу производить обмен.

Для обмена нам будет необходимо выдать разрешение контракту SwapRouter02 протокола Uniswap использовать в нужном количестве наши USDt

токены.

Находим в эксплорере по адресу контракт USDT. В методах записи находим метод approve.

Указываем адрес распорядителя - адрес контакта SwapRouter02 протокола, который также можно найти для нашей сети в документации Uniswap.

Указываем сумму - 1 USDt - 1 000 000 с учетом количества знаков после запятой (значение в публичной переменной decimals у контракта USDT).

Подписываем транзакцию.

Далее на контракте SwapRouter02 находим метод exactInputSingle.

Указываем значения параметров:

  • payableAmount - количество передаваемого Эфира в транзакции 0 - мы не будем менять Эфир на то-то сейчас.
  • tokenIn - адрес токена USDT - мы его будем менять на USDC.
  • tokenOut - адрес токена USDC - то, что хотим получить.
  • fee - указываем 10000 - мы хотим обменять на пуле именно с такой комиссией - 0,01%.
  • recipient - получатель usdc - копируем адрес, которым будем подписывать транзакцию. Но можно указать и другой адрес
  • deadline - до какого момента транзакцию можно будет выполнить - бывает, что транзакция не сразу подтверждается, подвисает и мы должны указать, до какого времени она еще актуальна для нас. Время указывается в формате unixtime, мы здесь укажем сколько угодно большое число.
  • amountIn - указываем количество ассета, который меняем - меняем 1 usdt - 1000000 с учетом дробной части после запятой.
  • amountOutMinimum - минимальное количество токенов usdc, которое мы хотим получить. Поставим значение 10 - с учётом количества знаков после запятой.
  • sqrtPriceLimitX96 - лимит цены (обычно 0, если мы не хотим ограничивать цену).

Подписываем транзакцию. Проверяем транзакцию. Видим, что протокол забрал 1 USDT и зачислил нам некоторое количество токенов USDC - чуть меньше 1 доллара.

Простой обмен завершён!

[Продолжение следует]