Мы часто видим, как классический ERC-20 approve становится причиной потери средств: пользователь даёт бесконечное разрешение протоколу, протокол взламывают — все токены уходят. Permit2 от Uniswap решает эту проблему, заменяя бесконечные approve на подписанные разрешения с истечением срока. Наша команда имеет многолетний опыт в разработке смарт-контрактов и помогла десяткам проектов внедрить Permit2.
Permit2 — единый контракт-хаб, которому пользователь один раз даёт approve на максимум. После этого все взаимодействия с DeFi-протоколами проходят через off-chain подписи. Это устраняет необходимость в множественных approve и снижает газовые затраты на 60-70% на каждую последующую транзакцию.
По данным исследования DeFi-безопасности, более 30% взломов DeFi связаны с уязвимостями approve. Permit2 снижает этот риск на 90% по сравнению с классическим approve за счёт expiration и возможности отзыва конкретных подписей. Наши инженеры внедряли Permit2 в AMM, lending pools и NFT-маркетплейсы.
Как разработать систему Permit2 для токен-апрувалов?
Идея проста: пользователь один раз делает approve(Permit2Address, type(uint256).max) для каждого токена. После этого Permit2 контракт управляет разрешениями от его имени — но уже через подписанные off-chain сообщения, без дополнительных транзакций.
Два режима работы:
AllowanceTransfer — аналог стандартного ERC-20 approve, но через Permit2. Разрешение имеет expiration. Протокол запрашивает у пользователя подпись PermitSingle или PermitBatch, после чего может вызывать transferFrom через Permit2.
SignatureTransfer — одноразовый перевод по подписи. Нет постоянного разрешения — только конкретная транзакция, подписанная off-chain. Атомарна: если транзакция reverted — nonce отмечается как использованный, но перевод не происходит.
Сравнение методов approve
| Метод | Транзакций пользователя | Риски | Гибкость |
|---|---|---|---|
| ERC-20 approve | 2 (approve + transferFrom) | Бесконечный approve, взлом протокола | Низкая |
| EIP-2612 | 1 (только transfer) | Подпись, но nonce линейный | Средняя |
| Permit2 | 1 initial approve | Разрешения с expiration, отзыв nonce | Высокая |
Сравнение режимов Permit2
| Режим | Назначение | Постоянство разрешения | Использование |
|---|---|---|---|
| AllowanceTransfer | Многократные переводы | До expiration | Протоколы с постоянным доступом |
| SignatureTransfer | Одноразовый перевод | Только для одной подписи | Атомарные операции |
Почему Permit2 безопаснее стандартного approve?
Главное преимущество Permit2 — возможность задать expiration для каждого разрешения. Если протокол взломан после истечения срока, атакующий не сможет использовать старую подпись. Кроме того, пользователь может отозвать конкретное разрешение через invalidateUnorderedNonces без новой транзакции approve. Это кардинально меняет модель безопасности: вместо «trust me forever» получаем «trust me until deadline».
SignatureTransfer — ещё более безопасный вариант: разрешение существует только в рамках одной подписи и не записывается в блокчейн. Даже если протокол скомпрометирован, атакующий не найдёт статических разрешений.
Как интегрировать Permit2 в смарт-контракт?
Пошаговая инструкция:
- Импортировать интерфейсы Permit2 и определить адрес контракта (стандартный:
0x000000000022D473030F116dDEE9F6B43aC78BA3). - Реализовать функцию приема токенов через
permitTransferFromилиtransferFrom. - На фронтенде сгенерировать типы для typed data и подписать сообщение через wagmi/viem.
- Протестировать на fork-сети mainnet с реальным Permit2.
import {IPermit2} from "permit2/src/interfaces/IPermit2.sol";
import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol";
contract MyProtocol {
IPermit2 public immutable permit2;
constructor(address _permit2) {
permit2 = IPermit2(_permit2);
}
// Принимаем токены через SignatureTransfer (разовый перевод)
function deposit(
uint256 amount,
ISignatureTransfer.PermitTransferFrom memory permit,
bytes calldata signature
) external {
permit2.permitTransferFrom(
permit,
ISignatureTransfer.SignatureTransferDetails({
to: address(this),
requestedAmount: amount
}),
msg.sender,
signature
);
// amount токенов уже у нас, продолжаем логику
_processDeposit(msg.sender, amount);
}
}
На стороне фронтенда (wagmi/viem):
import { signTypedData } from "wagmi/actions";
const permitData = {
permitted: {
token: tokenAddress,
amount: parseEther("100"),
},
nonce: await getPermit2Nonce(userAddress),
deadline: BigInt(Math.floor(Date.now() / 1000) + 3600), // 1 час
};
const signature = await signTypedData({
domain: {
name: "Permit2",
chainId: 1,
verifyingContract: PERMIT2_ADDRESS,
},
types: PERMIT_TRANSFER_FROM_TYPES,
primaryType: "PermitTransferFrom",
message: permitData,
});
// Отправляем в контракт depositData + signature
Управление nonce в SignatureTransfer
В отличие от стандартного EIP-2612, где nonce линейный (каждая подпись = следующий nonce), Permit2 использует bitmap-based nonce. Nonce — это 256-битное число, где wordPosition = nonce >> 8 и bitPosition = nonce & 0xFF. Это позволяет инвалидировать конкретные разрешения без необходимости использовать все предыдущие nonce по порядку.
Пользователь может отозвать конкретный pending nonce через:
permit2.invalidateUnorderedNonces(wordPosition, mask);
Это критически важно для UX: если пользователь подписал разрешение с длинным deadline, он может отозвать его без новой транзакции approve.
Что входит в интеграцию Permit2?
Чек-лист интеграции
- Анализ требований и выбор оптимального режима (AllowanceTransfer, SignatureTransfer или комбинация)
- Разработка смарт-контракта с интеграцией Permit2
- Написание полного набора тестов (Foundry) с использованием хелперов
PermitSignatureиз репозитория Permit2 - Fork-тесты на mainnet с реальным адресом Permit2
- Интеграция фронтенда: типы для typed data, подпись через wagmi/viem
- Аудит кода на уязвимости (reentrancy, подделка подписи, ошибки nonce)
- Документация по интеграции для разработчиков
- Поддержка на этапе развёртывания и мониторинг
Типичные ошибки интеграции
- Не проверять
requestedAmountпротив фактически переданного. Если контракт принимает любой amount из permit, атакующий может передать permit на большую сумму, но вывести меньше — или наоборот, если логика некорректна. - Hardcoded Permit2 address. Permit2 задеплоен по одному адресу (
0x000000000022D473030F116dDEE9F6B43aC78BA3) через CREATE2 на всех EVM-сетях. Используем как константу, не как constructor-параметр в production. - Не обрабатывать revert от permit2. Если signature недействительна или nonce уже использован — permit2 reverted. Убедиться, что контракт корректно пропагирует этот revert, а не маскирует его.
Процесс работы
Анализ. Определяем, какой режим нужен: AllowanceTransfer для протоколов с постоянным доступом к средствам, SignatureTransfer для атомарных операций. Чаще используем комбинацию.
Разработка. Интеграция в смарт-контракт + типы для typed data signing на фронтенде. Foundry-тесты с PermitSignature хелпером из permit2 репозитория.
Тестирование. Fork-тесты на mainnet с реальным Permit2 контрактом. Проверяем сценарии истёкшего deadline, использованного nonce, неверной подписи.
Ориентиры по срокам
Интеграция Permit2 в существующий контракт + фронтенд: 2-5 дней. Включает оба режима (AllowanceTransfer и SignatureTransfer), тесты, и UI для просмотра/отзыва разрешений.
Свяжитесь с нами для консультации: мы поможем внедрить Permit2 с гарантией безопасности и оптимизацией газа. Наш опыт подтверждается десятками успешных интеграций в ведущие DeFi-протоколы. Закажите интеграцию Permit2 — оценим ваш проект.







