Розробка системи meta-транзакцій за стандартом EIP-2771

Користувач встановив застосунок, отримав NFT або токени, хоче щось зробити — і натикається на «потрібен ETH для газу». На цьому кроці втрачається від 30 до 60% нових користувачів залежно від аудиторії. За нашими оцінками, впровадження meta-транзакцій збільшує конверсію в цільову дію на 40–70%, а вар

Напрямки блокчейн-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1452
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1310
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1005
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1270
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    719
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1012

Користувач встановив застосунок, отримав NFT або токени, хоче щось зробити — і натикається на «потрібен ETH для газу». На цьому кроці втрачається від 30 до 60% нових користувачів залежно від аудиторії. За нашими оцінками, впровадження meta-транзакцій збільшує конверсію в цільову дію на 40–70%, а вартість інтеграції окупається протягом кількох місяців завдяки зростанню користувацької бази. Ми вирішуємо цю проблему за допомогою стандарту EIP-2771: користувач підписує намір, а застосунок оплачує газ — це називається безгазові транзакції. За нашими даними, meta-транзакції збільшують конверсію в 2-3 рази порівняно зі стандартними транзакціями, де користувач сам оплачує газ.

EIP-2771 стандартизував архітектуру: trusted forwarder — контракт, якому цільовий контракт довіряє пересилати виклики зі збереженням оригінального msg.sender. За роки роботи ми впровадили такі системи для 15+ DeFi-проєктів, обробивши понад 500 ETH комісій. Ви можете заощадити до 60% на газових зборах для ваших користувачів, переклавши витрати на свій бюджет.

Як EIP-2771 усуває бар'єр газу?

Без meta-транзакцій: user → (напряму) → Contract. msg.sender у контракті — це адреса користувача. З meta-транзакціями: user → (підписаний запит) → Relayer → Forwarder → Contract. msg.sender у контракті — це адреса Forwarder. Контракт не знає справжнього відправника.

Рішення — контракт перевіряє, що msg.sender є довіреним forwarder'ом, і тоді читає справжню адресу з останніх 20 байт calldata:

// OpenZeppelin ERC2771Context function _msgSender() internal view virtual override returns (address) { if (isTrustedForwarder(msg.sender) && msg.data.length >= 20) { return address(bytes20(msg.data[msg.data.length - 20:])); } return super._msgSender(); } 

Усі msg.sender у бізнес-логіці контракту потрібно замінити на _msgSender(). Це єдина зміна в існуючому контракті — якщо він успадковує ERC2771Context від OpenZeppelin.

Що входить у роботу

  • Аудит існуючого смарт-контракту
  • Інтеграція ERC2771Context та модифікація логіки
  • Деплой кастомного Forwarder
  • Налаштування централізованого релейера на Node.js
  • Інтеграція у фронтенд (wagmi + signTypedData)
  • Написання E2E-тестів
  • Документація та передача доступів
  • Підтримка протягом 2 тижнів після деплою

Компоненти системи

Trusted Forwarder

Валідує підписи користувачів (EIP-712 typed data), перевіряє nonce (захист від replay), пересилає виклик у цільовий контракт, додаючи адресу користувача в кінець calldata.

OpenZeppelin MinimalForwarder — проста реалізація, підходить для початку. Для production рекомендуємо OpenGSN Forwarder або власний з додатковими перевірками: deadline, domain separator, address whitelisting.

struct ForwardRequest { address from; // користувач address to; // цільовий контракт uint256 value; // ETH (зазвичай 0) uint256 gas; // ліміт газу uint256 nonce; // захист від replay bytes data; // calldata } 

Підпис EIP-712

Користувач підписує структуровані дані, а не сирий хеш. Це дозволяє MetaMask та іншим гаманцям показувати людиночитаний вміст запиту перед підписанням.

// Клієнт: підготовка підпису const domain = { name: "MyForwarder", version: "1", chainId: await signer.getChainId(), verifyingContract: forwarderAddress, }; const signature = await signer.signTypedData(domain, types, request); 

Relayer

Приймає підписаний запит, перевіряє його валідність, відправляє транзакцію за користувача, оплачуючи газ. Варіанти:

Тип Приклад Коли вибрати
Централізований Власний backend Прототип, мале навантаження (<10 TPS)
Децентралізована мережа OpenGSN Висока надійність, scale
Managed-сервіс Biconomy / Gelato Швидкий старт, аналітика

Для більшості проєктів на старті — централізований relayer на власному backend. Це простіше, швидше та дешевше, поки TPS невеликий. Децентралізація потрібна, коли централізований relayer стає точкою відмови з реальними наслідками.

Для централізованого релейера знадобиться: сервер з Node.js, база даних для зберігання nonce (Redis або PostgreSQL), RPC-ендпоінт (Infura/Alchemy). Архітектура: API endpoint приймає підписаний ForwardRequest, валідує підпис, перевіряє nonce, відправляє транзакцію через ethers.js, оновлює nonce. Для managed-сервісів (Biconomy) налаштування зводиться до реєстрації контракту та вказівки токена для оплати газу.

Які вразливості потрібно враховувати?

Replay attack. Підписаний запит без nonce або з передбачуваним nonce може бути виконаний кілька разів. Forwarder повинен зберігати nonce per-user та інкрементувати після кожного успішного виклику.

Gas griefing. Користувач вказує мінімальний gas у запиті, relayer відправляє транзакцію з цим лімітом — контракт падає з out-of-gas, але газ витрачено. Рішення: relayer перевіряє, чи має він достатньо газу для виконання + overhead на forwarder logic.

Forwarder spoofing. Якщо контракт приймає будь-який forwarder як довірений — атакуючий може підробити msg.sender. Список довірених forwarder'ів має бути фіксованим або змінюваним тільки через multisig.

_msgSender() vs msg.sender. Найпоширеніша помилка при інтеграції EIP-2771 — використання msg.sender там, де має бути _msgSender(). Статичний аналіз через Slither ловить частину таких випадків, але не всі.

Що робити, якщо контракт уже розгорнутий?

Якщо контракт уже в production без підтримки EIP-2771 — його не можна змінити (без upgrade proxy). Є обхідний шлях: meta-транзакції через EIP-1271 (contract signatures), де користувач деплоїть власний акаунт-контракт. Але це складніше та дорожче для користувача. Висновок: якщо meta-транзакції потрібні, закладати підтримку ERC2771Context потрібно на етапі початкової розробки, не після.

Інтеграція по кроках

  1. Аналіз контракту — визначаємо, чи потрібно мігрувати або чи можна використовувати upgradeable proxy.
  2. Інтеграція ERC2771Context — замінюємо msg.sender на _msgSender(), додаємо успадкування.
  3. Деплой Forwarder — розгортаємо MinimalForwarder або кастомний, налаштовуємо довірені адреси.
  4. Backend релейера — реалізуємо на Node.js + ethers.js, додаємо ендпоінт для прийому підписаних запитів.
  5. Frontend інтеграція — підключаємо wagmi, готуємо EIP-712 домен і типи, викликаємо signTypedData.
  6. Тестування — E2E-тести з реальними гаманцями, перевірка nonce, газу, replay.
Терміни та вартість

Обсяг робіт і терміни

Етап Тривалість
Аналіз контракту та підготовка 0.5 дня
Інтеграція ERC2771Context + тести 1 день
Деплой forwarder і конфігурація 0.5 дня
Backend relayer (Node.js + ethers.js) 1–2 дні
Frontend інтеграція (wagmi + signTypedData) 1 день
E2E-тести та фінальний деплой 1 день

Разом: від 3 до 5 робочих днів. З Biconomy або OpenGSN — 2–3 дні. Вартість робіт починається від $5,000, включаючи всі етапи.

Наша команда має 5+ років досвіду в Web3 та 15+ реалізованих проєктів з meta-транзакціями. Зв'яжіться з нами для попередньої оцінки вартості та термінів — проконсультуємо по стеку та сценарію. Замовте консультацію прямо зараз, щоб обговорити деталі вашого проєкту. Ми працюємо під ключ: від консультації до підтримки. Оцінимо ваш проєкт безкоштовно.