Ми часто бачимо, як класичний 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 контрактом. Перевіряємо сценарії з expired deadline, використаним nonce, невірним підписом.
Орієнтири за термінами
Інтеграція Permit2 в існуючий контракт + фронтенд: 2-5 днів. Включає обидва режими (AllowanceTransfer і SignatureTransfer), тести та UI для перегляду/відкликання дозволів.
Зв'яжіться з нами для консультації: ми допоможемо впровадити Permit2 з гарантією безпеки та оптимізацією газу. Наш досвід підтверджується десятками успішних інтеграцій у провідні DeFi-протоколи. Замовте інтеграцію Permit2 — оцінимо ваш проєкт.







