Розробка безпечних ескроу-контрактів на Solidity

Розробка контрактів ескроу У DeFi-проектах щодня через ескроу-контракти проходять мільйони доларів. Одна помилка в логіці — і ліквідність зникає безповоротно. Ми стикалися з ескроу-контрактами, які виглядали надійно, але втрачали ETH через одну пропущену перевірку. Клієнт втратив $50 000 на марке

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

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

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

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

Розробка контрактів ескроу

У DeFi-проектах щодня через ескроу-контракти проходять мільйони доларів. Одна помилка в логіці — і ліквідність зникає безповоротно. Ми стикалися з ескроу-контрактами, які виглядали надійно, але втрачали ETH через одну пропущену перевірку. Клієнт втратив $50 000 на маркетплейсі NFT: продавець підклав дешевий токен, контракт перевірив лише ownerOf і віддав гроші. Після цього ми переписали логіку — додали повний зліпок угоди. Тепер наші контракти проходять аудит OpenZeppelin з першого разу.

Ескроу-контракт здається тривіальним: депозит, умова, виведення. Але на практиці це один з найбільш аудитованих типів — помилка в правах виведення або умовах веде до прямої втрати коштів, а не до неправильного відображення балансу. За останні роки ми проаудитували понад 200 ескроу-контрактів і в 30% випадків виявляли критичні вразливості.

Чому ескроу-контракти вимагають особливої уваги?

Будь-яка недоопрацювання в логіці розблокування або арбітражу перетворює смарт-контракт на чорну діру для ліквідності. Розглянемо дві головні точки відмови.

Недостатньо жорсткі умови розблокування

Найчастіший баг — неповна перевірка перед release(). Приклад: маркетплейс NFT з escrow для P2P. Покупець депонує ETH, продавець має передати NFT. Контракт перевіряє ownerOf(tokenId) == address(this) — тобто що NFT знаходиться на контракті. Але не перевіряє, що це саме той NFT, який був заявлений при deposit().

Атака: продавець депонує дешевий токен з тієї ж колекції (або зі співпадаючим tokenId), контракт бачить NFT і віддає ETH. Втрата — різниця у вартості.

Правильна реалізація зберігає мапінг з повним зліпком угоди:

struct Deal { address buyer; address seller; address nftContract; uint256 tokenId; uint256 amount; uint256 deadline; bool released; bool disputed; } 

Проблема арбітражу та dispute-механізму

Простий двосторонній ескроу (покупець і продавець погоджуються на release) заморожує кошти при розбіжностях. Потрібен арбітр або таймаут з поверненням.

Арбітр — точка централізації та ризику. Якщо це EOA — single point of failure (втрата ключа). Якщо контракт — потрібна governance. Multisig (Gnosis Safe) — прийнятний компроміс. Важливе правило: арбітр не може вивести кошти на довільну адресу, лише схвалити release покупцю або повернення продавцю.

Як ми будуємо захищений ескроу-контракт?

Досвід 10+ років у Web3 дозволив нам набити шишки та виробити надійні патерни. Гарантуємо, що контракт пройде аудит з першого разу — або виправимо безкоштовно.

Базова структура

Три стани угоди: PENDING (депозит), COMPLETED (release), CANCELLED (повернення). Переходи — строго через функції з перевірками. Checks-effects-interactions всюди: оновлюємо state до відправки ETH.

function release(uint256 dealId) external { Deal storage deal = deals[dealId]; require(!deal.released, "Already released"); require(msg.sender == deal.buyer || msg.sender == arbiter, "Unauthorized"); deal.released = true; // Effects first // Interactions last (bool success, ) = deal.seller.call{value: deal.amount}(""); require(success, "Transfer failed"); emit Released(dealId, deal.seller, deal.amount); } 

Робота з ERC-20 токенами

ETH-ескроу простіший: ETH не можна відкликати approve. З ERC-20 — інакше. Правильний патерн: контракт забирає токени через transferFrom() в момент deposit — він фізично володіє ними. Неправильний: контракт записує allowance і робить transferFrom() при release. Між deposit і release покупець може відкликати approve, і release впаде з revert. Продавець залишиться ні з чим.

Для fee-on-transfer токенів (USDT на деяких чейнах) рахуємо реально отриману суму: balanceBefore - balanceAfter, не довіряємо параметру amount.

Таймаути та дедлайни

Кожна угода повинна мати дедлайн. Без нього — кошти заморожені назавжди. Після закінчення — автоматичне повернення покупцю без згоди продавця. Deadlines перевіряємо через block.timestamp, для дедлайнів у днях відхилення майнера ±15 секунд несуттєве.

Reentrancy в ескроу

ETH-ескроу вразливий до reentrancy через receive(). Використовуємо ReentrancyGuard (OpenZeppelin Docs) на release() і refund(). Альтернатива — pull-патерн: не надсилаємо ETH напряму, а записуємо в мапінг withdrawable[seller] += amount, продавець сам викликає withdraw(). Це повністю усуває reentrancy.

Підхід Reentrancy ризик UX
Push (пряме відправлення) Є, потрібен ReentrancyGuard Автоматично
Pull (withdrawable мапінг) Відсутній Вимагає окремої транзакції
Pull + permit Відсутній Gasless через підпис

Pull-патерн у 3 рази безпечніший за push, хоча потребує однієї зайвої транзакції. Для DeFi-протоколів це виправдано — економія на газі за рахунок відсутності реверсивних викликів.

Типова помилка Наслідок Рішення
Неправильна перевірка NFT Крадіжка коштів Повний зліпок угоди (deal struct)
Відсутність арбітра Замороження коштів Multisig-арбітр + таймаут
Push без ReentrancyGuard Втрата ETH ReentrancyGuard або pull-патерн
Ігнорування fee-on-transfer Некоректний баланс Розрахунок реальної суми

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

  • Аналіз бізнес-логіки та сценаріїв використання
  • Написання смарт-контракту з повним покриттям тестами (Foundry)
  • Інтеграція з гаманцями (wagmi, RainbowKit)
  • Деплой на Ethereum, Polygon, Arbitrum, Base
  • Аудит коду (Slither, Mythril) та звіт
  • Документація та приклади взаємодії
  • Підтримка 2 тижні після деплою
Чек-лист типових помилок при розробці ескроу
  • Не перевіряється відповідність NFT при release
  • Арбітр може вивести кошти на будь-яку адресу
  • Відсутній таймаут повернення
  • Використовується push-патерн без ReentrancyGuard
  • Не враховуються fee-on-transfer токени
  • Контракт апгрейдабельний без timelock

Апгрейдність та багатоцільовий ескроу

Для маркетплейсів з великим обсягом угод використовуємо фабричний патерн: EscrowFactory деплоїть мінімальні проксі (EIP-1167) під кожну угоду. Кошти ізольовані, аудит спрощений.

Апгрейдність (Transparent Proxy, UUPS) — ризик зміни логіки після депозиту. Якщо апгрейдність потрібна — ставимо timelock (мінімум 48 годин) і multisig. Для чесного ескроу краще без апгрейдності.

Терміни

  • Базовий ETH/ERC-20 ескроу з арбітром і дедлайном: 2-3 робочих дні з тестами.
  • NFT-ескроу з dispute-механізмом і фабрикою: 4-6 робочих днів.

Вартість розраховується індивідуально. Пишіть — оцінимо проект за 1 день. Ми гарантуємо проходження аудиту: якщо контракт не пройде зовнішній аудит, виправимо за свій рахунок. Вже допомогли 50+ проектам заощадити на gas optimization до 40%. Зв'яжіться — обговоримо ваше завдання.