Skip to content
ChainConnect

Лимиты (Limits)

Что такое лимиты

Лимиты — это механизм защиты бриджа от масштабных атак и эксплойтов. Они ограничивают суточный объём переводов для каждого токена отдельно.

Назначение:

  • Защита от drainage атак (массовый вывод средств при взломе)
  • Ограничение потенциального ущерба при эксплойте
  • Время для реагирования на аномальную активность

Где применяется:

  • Контракты ProxyMultiVaultAlienJetton_V3 (alien токены)
  • Контракты ProxyMultiVaultNativeJetton_V3 (native токены)

Типы лимитов

Система поддерживает два типа суточных лимитов для каждого токена:

ТипОписаниеПрименение
Incoming (входящий)Ограничение на объём токенов, поступающих в сетьДепозиты из других сетей в TVM
Outgoing (исходящий)Ограничение на объём токенов, выводимых из сетиВывод из TVM в другие сети

Особенности

  • Лимиты устанавливаются на конкретный токен, а не глобально
  • Каждый лимит опционален — может быть не установлен (null)
  • Если лимит не установлен — проверка пропускается, трансфер проходит без ограничений
  • Лимиты не зависят от адреса пользователя — это общий суточный объём для токена

Структура данных

DailyLimits

solidity
struct DailyLimits {
    optional(uint128) incomingLimit;      // Лимит на входящие (null = без лимита)
    uint128 dailyIncomingVolume;          // Текущий суточный объём входящих

    optional(uint128) outgoingLimit;      // Лимит на исходящие (null = без лимита)
    uint128 dailyOutgoingVolume;          // Текущий суточный объём исходящих

    uint32 dayStartTimestamp;             // Timestamp начала текущего "дня"
}

Механизм проверки лимитов

Алгоритм проверки

Алгоритм проверки лимитов

Определение "дня"

День определяется делением block.timestamp на 86400 (секунд в сутках).

  • День сбрасывается в 00:00 UTC
  • При смене дня объёмы обнуляются
  • Обновляется dayStartTimestamp

Когда проверяется лимит

НаправлениеМомент проверки
Incoming (deposit)После подтверждения event relays
Outgoing (withdraw)При получении токенов на burn/transfer

Формула проверки

  • Incoming: dailyIncomingVolume + amount > incomingLimit → LimitReached
  • Outgoing: dailyOutgoingVolume + amount > outgoingLimit → LimitReached

Важно

Проверка > (строго больше), не >=. Если лимит = 100 и текущий volume = 0, то трансфер на 100 пройдёт (100 > 100 = false).

Сценарии при достижении лимита

Outgoing (исходящий) — LimitReached

При превышении лимита на вывод:

  1. Токены возвращаются отправителю
  2. Событие OutgoingLimitReached(token) эмитится
  3. Трансфер не создаётся

Incoming (входящий) — LimitReached

При превышении лимита на ввод:

  1. Event контракт переходит в статус LimitReached (код 5)
  2. Устанавливается limitApprover адрес
  3. Событие LimitReached(approver) эмитится
  4. Трансфер откладывается до решения approver'а

Действия при LimitReached (входящий)

LimitApprover может выполнить одно из трёх действий:

ДействиеФункцияРезультат
ApproveapproveLimit()Трансфер выполняется, токены минтятся получателю
Cancelcancel()Токены возвращаются в исходную сеть
RejectrejectLimit()Event отклоняется, средства остаются в исходной сети

Retry механизм

Пользователь или инициализатор могут вызвать retry() для повторной попытки трансфера (например, после сброса лимита в новые сутки).

Восстановление лимита

Лимит автоматически сбрасывается в 00:00 UTC следующего дня. Ручной сброс не предусмотрен — только изменение самого лимита через setTokenDailyLimits().

Управление лимитами

Установка лимитов

solidity
setTokenDailyLimits(_token, _incomingLimit, _outgoingLimit)

Параметры:

  • _token — адрес токена
  • _incomingLimit — лимит на входящие (null = без лимита)
  • _outgoingLimit — лимит на исходящие (null = без лимита)

Права доступа: Только owner контракта

Установка LimitApprover

solidity
setLimitApprover(approverAddress)

Права доступа: Только owner контракта

Чтение лимитов

  • getDailyLimits(token) — возвращает структуру DailyLimits для токена
  • getLimitApprover() — возвращает адрес текущего approver'а

Лимиты по умолчанию

По умолчанию лимиты не установлены (null). Это означает неограниченные трансферы до явной установки лимитов администратором.

API/Contract Reference

Proxy контракты (Alien и Native)

ФункцияДоступОписание
setTokenDailyLimits()ownerУстановить/изменить лимиты для токена
getDailyLimits()publicПолучить текущие лимиты и объёмы
setLimitApprover()ownerУстановить адрес approver'а
getLimitApprover()publicПолучить адрес approver'а

Event контракты

ФункцияДоступОписание
approveLimit()limitApproverОдобрить трансфер при LimitReached
cancel()limitApproverОтменить и вернуть средства
rejectLimit()limitApproverОтклонить трансфер
retry()recipient/initializerПовторить попытку трансфера

События (Events)

СобытиеКогда эмитится
OutgoingLimitReached(address token)При превышении исходящего лимита
LimitReached(address approver)При превышении входящего лимита

Ошибки и Edge Cases

Коды ошибок

КодКонстантаОписание
2335SENDER_IS_NOT_LIMIT_APPROVERВызывающий не является limit approver
2324WRONG_STATUSНеверный статус для операции

Edge Cases

СитуацияПоведение
Лимит = 0Любой трансфер > 0 превысит лимит
Лимит = nullБез ограничений
Первый трансфер дняОбъём сбрасывается, затем добавляется сумма
Трансфер точно равен лимитуПройдёт (проверка >, не >=)
limitApprover = zero addressapproveLimit() завершится с ошибкой

Важные замечания

  1. Частичное выполнение НЕ поддерживается — трансфер либо проходит полностью, либо отклоняется
  2. Лимиты проверяются ПОСЛЕ подтверждения relays для incoming трансферов
  3. Лимиты проверяются ДО создания event для outgoing трансферов
  4. При outgoing LimitReached токены возвращаются мгновенно, не требуют ручного вмешательства

ChainConnect Bridge Documentation