Universal Router — это смарт-контрактный маршрутизатор нового поколения, предназначенный для объединения различных операций в экосистеме децентрализованных финансов в одну транзакцию. Основная идея заключается в том, чтобы предоставить единый интерфейс для выполнения сложных цепочек действий: обмен токенов, работа с NFT, управление ликвидностью и другие операции.
В отличие от классических роутеров, которые ограничены одной функцией (например, только swap), Universal Router позволяет комбинировать несколько типов действий в рамках одного вызова.
В основе Universal Router лежит концепция командного исполнения (command-based execution). Вместо вызова конкретной функции пользователь формирует последовательность команд, каждая из которых описывает отдельное действие.
Ключевые элементы:
Такой подход позволяет:
Все действия выполняются в рамках одной транзакции. Если хотя бы один шаг завершается с ошибкой — откатывается вся цепочка.
Пример:
Все три шага либо выполняются полностью, либо не выполняются вовсе.
Universal Router может взаимодействовать сразу с несколькими протоколами:
Это достигается за счёт унифицированной системы команд.
Возможность строить сложные маршруты:
Каждая команда кодируется одним байтом. Этот байт определяет тип операции.
Пример логики:
0x00 — swap exact input
0x01 — swap exact output
0x02 — transfer token
0x03 — wrap ETH
0x04 — unwrap ETH
...
Команды объединяются в массив:
const commands = '0x000104';
Каждая команда имеет соответствующий набор параметров. Все входные
данные передаются в массиве inputs.
Пример:
const inputs = [
encodeSwap(...),
encodeTransfer(...),
encodeWrap(...)
];
Важно:
Основная функция Universal Router:
execute(bytes commands, bytes[] inputs, uint256 deadline)
Параметры:
Пример вызова через JavaScript (ethers.js):
await router.execute(commands, inputs, deadline);
import { ethers } from "ethers";
const router = new ethers.Contract(
ROUTER_ADDRESS,
ROUTER_ABI,
signer
);
Команды формируются вручную или через SDK:
const COMMAND_SWAP = 0x00;
const COMMAND_TRANSFER = 0x02;
const commands = ethers.utils.hexConcat([
COMMAND_SWAP,
COMMAND_TRANSFER
]);
Для каждой команды требуется ABI-кодирование:
const abi = ethers.utils.defaultAbiCoder;
const swapInput = abi.encode(
["address", "uint256", "uint256"],
[tokenIn, amountIn, amountOutMin]
);
const commands = '0x0002';
const inputs = [
encodeSwap(tokenIn, tokenOut, amount),
encodeTransfer(recipient, amountOut)
];
await router.execute(commands, inputs, deadline);
1. Универсальность
Один контракт заменяет множество специализированных:
2. Снижение затрат газа
3. Композиция логики
Возможность строить сложные сценарии:
ошибки в inputs могут привести к потере средств
важно проверять:
Код становится менее очевидным:
0x000104
не даёт интуитивного понимания без документации.
Контракт выполняет команды последовательно:
Псевдологика:
for (uint i = 0; i < commands.length; i++) {
executeCommand(commands[i], inputs[i]);
}
Universal Router умеет работать с:
Команды:
Параметр deadline защищает от:
Пример:
const deadline = Math.floor(Date.now() / 1000) + 60 * 10;
Universal Router особенно полезен для:
Universal Router — это не просто контракт, а интерпретатор транзакций, который:
Такой подход приближает смарт-контракты к модели программируемых транзакций, где логика формируется на стороне клиента и исполняется единым вызовом.