Разработка системы рекуррентных крипто-платежей
Криптовалюта по природе не поддерживает рекуррентные платежи: блокчейн-транзакция — это всегда явное действие инициатора. Подписать «списывать USDC каждый месяц» нельзя так же, как с банковской картой. Любая система подписок в крипте — это архитектурный компромисс между удобством пользователя, безопасностью и децентрализацией.
Два принципиально разных подхода
Pull-платежи через смарт-контракт
Пользователь один раз подписывает транзакцию, дающую контракту право списывать токены через approve. Контракт сам инициирует списание по расписанию через внешний триггер (Keeper, Gelato Automation, Chainlink Automation).
Ключевая уязвимость этого подхода: approve на неограниченную сумму — стандартная практика, но риск. Если контракт скомпрометирован — атакующий списывает всё. Современная альтернатива — EIP-2612 Permit (gasless approve с подписью) с лимитом суммы и сроком действия, или ERC-20 permit flow.
Вторая проблема: Keeper должен знать, когда наступил срок платежа. Это либо on-chain mapping subscriber → nextPaymentTimestamp, либо внешний планировщик. Если Keeper упал или не вызвал функцию вовремя — платёж задерживается. Нет механизма «сам списался в нужное время» без внешнего вызова.
Subscription contract storage:
subscriptions: mapping(address => Subscription)
struct Subscription {
uint256 amount;
uint256 interval; // секунды
uint256 nextPayment; // timestamp следующего списания
address token;
bool active;
}
Функция charge(address subscriber) проверяет block.timestamp >= nextPayment, выполняет transferFrom, обновляет nextPayment. Вызывается Keeper-сетью.
Кастодиальный подход
Пользователь депонирует средства на кастодиальный счёт (смарт-контракт-кошелёк или централизованный backend). Списание инициирует бизнес-логика на стороне оператора. Проще реализовать, работает без Keeper-инфраструктуры, но требует доверия к оператору.
Гибрид: пользователь депонирует в non-custodial контракт с возможностью вывода в любой момент, а оператор может списывать только фиксированную сумму с фиксированным интервалом. Параметры зафиксированы в контракте при создании подписки и не могут быть изменены оператором.
Интеграция с Gelato Automation
Для pull-платёжной системы нужен надёжный Keeper. Gelato Automation (бывший Gelato Network) позволяет задать условие и функцию для вызова, берёт газ из депозита или через 1Balance.
Регистрируем задачу:
const { taskId } = await automate.createTask({
execAddress: subscriptionContract.address,
execSelector: iface.getSighash("chargeAll"),
resolverAddress: resolverContract.address,
resolverData: iface.encodeFunctionData("checker"),
name: "Charge subscriptions",
});
Resolver-контракт — это view-функция, которая возвращает (bool canExec, bytes calldata execPayload). Gelato вызывает её off-chain и, если canExec = true, отправляет транзакцию. Resolver может проверять, есть ли подписки со сроком в текущем блоке.
Проблема газа при большом количестве подписок. chargeAll() в одной транзакции — это unbounded loop, классический вектор gas griefing. При 1000 подписок транзакция упрётся в block gas limit. Решение: батчинг с пагинацией, Keeper вызывает chargeBatch(uint256 offset, uint256 limit), или каждая подписка — отдельная задача в Gelato.
Отмена подписки и обработка недостаточного баланса
Пользователь должен иметь возможность отменить подписку в любой момент. Контракт: cancelSubscription() устанавливает active = false. При этом approval на токены остаётся — нужно явно инструктировать пользователя сделать approve(subscriptionContract, 0) или реализовать это автоматически в функции отмены через IERC20.approve(address(this), 0) (но это работает только если контракт является spender).
При недостаточном балансе transferFrom ревертируется, и Keeper получает ошибку. Важно не помечать подписку как неактивную автоматически — это может быть временная нехватка средств. Правильно: счётчик неуспешных попыток, после N попыток — пауза с уведомлением через event.
Сроки
Базовая система рекуррентных платежей (смарт-контракт + Gelato Automation + базовый frontend) — 5 рабочих дней. Система с кастомным resolver, управлением подписками, поддержкой нескольких токенов и мониторингом — 7-10 дней.
Стоимость рассчитывается после анализа требований к модели монетизации и целевым чейнам.







