Аудит универсального маршрутизатора Uniswap версии 2.1 и периферии версии 4

Источник: OpenZeppelin•

Аудит универсального маршрутизатора Uniswap версии 2.1 и периферии версии 4

OpenZeppelin's differential audit of Uniswap Universal Router 2.1 and v4 Periphery: per-hop slippage checks, RouteSigner and Across bridging. Both issues resolved.

8 октября 2026 года, 8 октября 2026 года

  • Безопасность OpenZeppelin

Результаты: общее количество проблем — 2 (2 решено). Критические: 0 (0 решено) · Высокие: 0 (0 решено) · Средние: 0 (0 решено) · Низкие: 1 (1 решено)

Заметки и дополнительная информация: 1 замечание (1 решено)

Область охвата

Компания OpenZeppelin провела дифференциальный аудит следующих двух запросов на извлечение кода:

Для запроса на извлечение кода № 457 в область охвата входили следующие файлы:

contracts├── base│ ├── Dispatcher.sol│ └── RouteSigner.sol├── deploy│ └── UnsupportedProtocol.sol├── interfaces│ ├── external│ │ └── IV3SpokePool.sol│ └── IUniversalRouter.sol├── libraries│ ├── Commands.sol│ ├── Locker.sol│ └── MaxInputAmount.sol├── modules│ ├── ChainedActions.sol│ └── uniswap│ ├── v2│ │ └── V2SwapRouter.sol│ └── v3│ └── V3SwapRouter.sol└── UniversalRouter.sol

Для запроса на извлечение кода № 497 в область охвата входили только файлы V4Router.sol и IV4Router.sol.

Обзор системы

Этот аудит охватывает серию изменений и дополнений к универсальному маршрутизатору Uniswap и периферии версии 4. Изменения включают введение двух новых контрактов: ChainedActions.sol и RouteSigner.sol, а также добавление проверок проскальзывания на каждом шаге для обменов.

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

Контракт RouteSigner помогает обеспечить безопасность офлайн-подписанных команд для системы маршрутизатора путем проверки подписей EIP-712, восстановления адреса подписавшего с помощью ECDSA и проверки номеров для предотвращения атак повторного использования. Он использует временное хранилище для хранения данных о подписавшем, намерении и данных на время транзакции, что делает его эффективным с точки зрения газа и безопасным, не оставляя постоянных данных позади. Помимо этого, был введен ChainedActions.sol, который позволяет осуществлять межцепевое связывание с использованием протокола Across.

Модель безопасности и предположения о доверии

Проверки проскальзывания на каждом шаге являются необязательными и могут не использоваться путем передачи пустого массива maxHopSlippage. Номера не помечаются как проверенные, если значение номера равно type(uint256).max. Имеется небольшое округление цены, которое используется для проверки проскальзывания на каждом шаге, но его влияние пренебрежимо из-за масштабирования amountIn на 1e18.

Привилегированные роли

Рецензируемые запросы на извлечение кода не вводят и не изменяют никаких привилегированных ролей.

Низкая серьезность

UniversalRouter может предоставить разрешение произвольному адресу

Функция _acrossV4DepositV3 контракта ChainedActions реализует логику, необходимую для поддержки связывания с использованием протокола Across. Перед вызовом локального SpokePool UniversalRouter предоставляет целевому spokePool разрешение на сумму inputAmount. Параметры spokePool и inputAmount являются значениями, предоставленными пользователем, что позволяет произвольному аккаунту получить разрешение от маршрутизатора на сумму inputAmount inputToken. UniversalRouter не предназначен для хранения каких-либо пользовательских средств, поэтому влияние ограничено ошибкой внешнего актера. Однако хорошей практикой является ограничение непреднамеренных одобрений. Для поддерживаемых цепей Across развертывает один SpokePool на каждую сеть.

Рассмотрите возможность добавления адреса SpokePool локальной сети в качестве неизменного значения, чтобы обеспечить, что одобрения будут предоставляться только целевому адресу контракта.

Обновление: проблема решена в pull request #461 путем преобразования адреса Spoke Pool в неизменный. Команда заявила:

“Исправлено”

Заметки и дополнительная информация

Отсутствие именованных параметров в отображении

Начиная с Solidity 0.8.18, отображения могут включать именованные параметры для обеспечения большей ясности относительно их назначения. Именованные параметры позволяют объявлять отображения в форме mapping(KeyType KeyName? => ValueType ValueName?). Эта функция повышает читаемость и поддерживаемость кода.

В состоянии переменной noncesUsed контракта RouteSigner отображение не имеет никаких именованных параметров.

Рассмотрите возможность добавления именованных параметров в отображения, чтобы улучшить читаемость и поддерживаемость кода.

Обновление: проблема решена в . Команда заявила:

“Исправлено”

Заключение

Проведенный аудит вводит две отдельные функции: во-первых, маршрутизатор V4 был обновлен для обеспечения проверок проскальзывания на каждом шаге. Во-вторых, универсальный маршрутизатор был обновлен для разрешения межцепевого связывания в качестве одной из своих принятых команд.

Не было выявлено никаких значительных проблем. Реализации функций были признаны надежными и хорошо структурированными.

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

О чём эта статья