Skip to content

Архитектура Trustless моста (TVM ↔ TVM)

Общее описание

Trustless мост — это децентрализованная кроссчейн система для передачи токенов между TVM-совместимыми сетями, такими как TON и Tetra L2. В отличие от relay-based моста (используемого для переводов между EVM и TVM сетями), Trustless мост не полагается на relay-ноды для подтверждения трансферов. Вместо этого система использует криптографическую верификацию на основе Merkle proofs и специализированных LiteClient контрактов.

Ключевая особенность архитектуры — математическое доказательство корректности каждой транзакции, которое может быть независимо проверено любым участником сети. Такой подход устраняет необходимость доверять централизованным операторам или группам валидаторов моста.

Ключевое преимущество

Пользователю не нужно доверять третьим сторонам — только криптографическим алгоритмам и консенсусу валидаторов TVM сети. Это обеспечивает полную децентрализацию трансферов: ни один актор не может заблокировать средства или подделать транзакцию без контроля большинства валидаторов сети.

Принципиальная схема

Принципиальная схема Trustless моста

Глоссарий

Native и Alien токены

Система оперирует двумя типами токенов в зависимости от их происхождения относительно текущей сети:

ТерминОписание
Native токенТокен, изначально созданный и существующий в данной сети. При трансфере в другую сеть блокируется (lock) в Proxy-контракте исходной сети, оставаясь в ней как обеспечение. Право собственности на эти заблокированные токены представлено соответствующими alien токенами в сети назначения.
Alien токенОбёрнутое (wrapped) представление токена из другой сети. Создаётся (mint) в сети назначения при входящем трансфере, полностью обеспечено заблокированными native токенами в исходной сети. При обратном трансфере сжигается (burn), освобождая соответствующие native токены.

Пример:

  • USDT в сети TON — это Native токен для TON
  • При трансфере USDT из TON в Tetra L2:
    • В TON: USDT блокируется в NativeProxy (остаётся Native, физически находится в исходной сети)
    • В Tetra L2: минтится USDT (Alien токен) — обёрнутая версия, полностью обеспеченная заблокированными токенами в TON

Компоненты верификации

Система верификации состоит из нескольких взаимосвязанных компонентов, обеспечивающих криптографическую проверку кроссчейн транзакций:

ТерминОписание
LiteClientСмарт-контракт легкого клиента, развёрнутый в каждой сети и хранящий актуальную информацию о ключевых блоках другой сети. Содержит текущий набор валидаторов, их веса (влияние в консенсусе), временные метки эпох. Автоматически обновляется Sync Service при смене эпох валидаторов. Выступает как доверенный источник истины о состоянии другой сети.
TransactionCheckerКонтракт для верификации транзакций через Merkle proofs. Проверяет включение транзакции в блок через Merkle proof, затем валидирует подписи блока через LiteClient. Работает как независимый арбитр, математически подтверждающий существование транзакции.
Proof ChainЦепочка криптографических доказательств, связывающая транзакцию с консенсусом валидаторов: Merkle proof транзакции → Merkle proof блока → верификация подписей валидаторов через LiteClient. Каждое звено цепи проверяется независимо, обеспечивая надёжность всей конструкции.
Key BlockКлючевой блок TVM сети, содержащий информацию о смене набора валидаторов (validator set rotation). Синхронизируется между сетями через Sync Service, обеспечивая актуальность информации о валидаторах в LiteClient контрактах.

Конфигурация и управление

Управление трансферами осуществляется через систему конфигурационных контрактов и специализированных proxy-контрактов:

ТерминОписание
EventConfigurationКонтракт конфигурации события, управляющий жизненным циклом Event-контрактов. Осуществляет деплой Event-контрактов для обработки входящих трансферов, верифицирует параметры событий (chainId, временные метки, источник события). Выступает как фабрика и валидатор событий.
NativeProxyКонтракт-прокси для управления native токенами. Выполняет блокировку (lock) токенов при исходящих трансферах, сохраняя их как обеспечение, и разблокировку (unlock) при входящих трансферах после верификации. Управляет комиссиями, дневными лимитами и ликвидностью.
AlienProxyКонтракт-прокси для управления alien токенами. Выполняет минтинг (создание) новых alien токенов при входящих трансферах и сжигание (burn) при исходящих. Управляет деплоем новых типов alien токенов и интеграцией с MergePool для объединения токенов из разных источников.
MergePoolКонтракт для объединения alien токенов из разных сетей в единое каноническое представление (canon token). Позволяет использовать токены одного типа, но из разных источников (например, USDT из TON и USDT из Ethereum), как взаимозаменяемые активы. Обрабатывает конвертацию между разными decimals.
Predeployed TokenЗаранее зарегистрированный токен для сценария native-native, когда токен является нативным в обеих сетях. Используется для специальных токенов (например, wrapped native токенов типа wTON), которые должны существовать как native в нескольких сетях одновременно.

Типы трансферов

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

ПотокДействие в сети отправленияДействие в сети назначенияEvent-контракт
Lock Native → Mint AlienNativeProxy блокирует native токеныAlienProxy создаёт соответствующие alien токеныMultiVaultTvmTvmEventAlien
Burn Alien → Unlock NativeAlienProxy сжигает alien токеныNativeProxy разблокирует соответствующие native токеныMultiVaultTvmTvmEventNative
Lock Native → Unlock NativeNativeProxy блокирует native токеныAlienProxy проверяет predeployed token и передаёт управление NativeProxy для разблокировкиMultiVaultTvmTvmEventAlien (!)

Структура трансфера

Каждый кросс-чейн трансфер представляет собой атомарную операцию, состоящую из двух логических частей, выполняемых последовательно:

  1. Часть в сети отправления — пользователь инициирует блокировку (для native) или сжигание (для alien) токенов, Proxy-контракт эмитит событие, содержащее все параметры трансфера
  2. Часть в сети назначения — система строит криптографическое доказательство (proof chain), верифицирует событие через TransactionChecker и LiteClient, затем выполняет минтинг (для alien) или разблокировку (для native) токенов получателю

Важно понимать, что обе части связаны криптографически: вторая часть может быть выполнена только при наличии математически корректного доказательства первой части.

Event-контракт

Для каждого трансфера в сети назначения деплоится индивидуальный Event-контракт — уникальный смарт-контракт, представляющий конкретную операцию трансфера. Event-контракт выполняет несколько критически важных функций:

  1. Защита от double-spending — адрес контракта детерминированно вычисляется из msgHash исходного сообщения через функцию деривации. Это математически гарантирует, что одна транзакция может быть обработана только один раз: повторная попытка деплоя Event-контракта с тем же msgHash завершится ошибкой на уровне TVM, так как контракт с таким адресом уже существует.

  2. Координация процесса верификации — Event-контракт управляет взаимодействием с TransactionChecker и LiteClient, отслеживая статус верификации и обрабатывая результаты.

  3. Участие в логике Merge — Event-контракт взаимодействует с MergePool/MergeRouter для определения, какой токен получит пользователь: derive-токен (специфичный для источника) или canon-токен (объединённое представление) на основе конфигурации MergePool.

  4. Управление edge cases — обработка ситуаций превышения лимитов и нехватки ликвидности, координация с провайдерами ликвидности.

Механизм верификации

Trustless верификация основана на математическом доказательстве того, что транзакция была включена в блок и этот блок был подтверждён валидаторами исходной сети через их криптографические подписи.

Обзор

Система верификации состоит из трёх взаимосвязанных компонентов:

  1. LiteClient — хранит актуальный набор валидаторов другой сети (публичные ключи, веса, параметры эпохи), выступая как источник истины о консенсусе
  2. TransactionChecker — верифицирует Merkle proofs транзакций и блоков, подтверждая математически корректное включение транзакции в блокчейн
  3. Sync Service — автоматически синхронизирует ключевые блоки между сетями, обеспечивая актуальность validator set в LiteClient

LiteClient и Key Blocks

LiteClient — это специализированный смарт-контракт, развёрнутый в каждой сети и хранящий информацию о текущем наборе валидаторов другой TVM сети (из которой приходят трансферы). Он работает как легковесная версия полной ноды, но хранит только информацию о ключевых блоках и validator set, без полной истории транзакций.

Информация обновляется автоматически при смене эпох валидаторов (validator set rotation) через специализированную службу Sync Service, которая отслеживает ключевые блоки и транслирует изменения между сетями.

Структура хранимых данных:

  • current_seq_no — номер последовательности текущего ключевого блока (monotonically increasing sequence number)
  • current_epoch_since/until — временные границы текущей эпохи валидаторов (unix timestamp), определяющие период действия validator set
  • current_cutoff_weight — минимальный порог подписей для подтверждения блока: 2/3 + 1 от общего веса валидаторов (византийский порог)
  • current_validators_set — словарь валидаторов: validator_index → (публичный ключ ed25519 + вес в консенсусе)

Процесс обновления validator set:

Обновление набора валидаторов — критически важная операция, требующая строгой верификации:

  1. Отслеживание key blocks: Sync Service непрерывно мониторит блокчейн исходной сети, отслеживая появление key blocks (блоков, содержащих информацию о смене validator set)

  2. Подготовка доказательства: При появлении нового key block Sync Service:

    • Скачивает полный блок с Merkle proof структурой
    • Собирает подписи валидаторов для этого блока
    • Формирует proof chain, связывающий блок с консенсусом
  3. Верификация на LiteClient: Sync Service вызывает new_key_block() на контракте LiteClient, передавая:

    • Данные блока
    • Merkle proof блока
    • Коллекцию подписей валидаторов
  4. Проверки LiteClient:

    • Корректность Merkle proof: проверка математической корректности proof структуры блока
    • Тип блока: верификация, что блок является key block (содержит ConfigParams с новым validator set)
    • Валидность подписей: проверка криптографических подписей блока через ed25519_check_signature() для каждого валидатора из текущего набора (используется existing validator set для подтверждения нового)
    • Достижение порога: проверка, что суммарный вес подписавших валидаторов ≥ cutoff_weight
  5. Обновление состояния: При успешной верификации LiteClient:

    • Извлекает новый validator set из ConfigParams key block
    • Обновляет current_validators_set с новыми публичными ключами и весами
    • Обновляет current_epoch_since/until с новыми временными границами эпохи
    • Вычисляет новый cutoff_weight = (total_weight * 2 / 3) + 1
    • Инкрементирует current_seq_no

Византийская отказоустойчивость

Cutoff weight формула (total_weight * 2 / 3) + 1 реализует классический византийский порог, гарантирующий безопасность при наличии до 1/3 злонамеренных или отказавших валидаторов.

В математическом выражении: для успешной атаки злоумышленнику необходимо скомпрометировать >1/3 всех валидаторов по весу. Если скомпрометировано ≤1/3, они физически не смогут набрать требуемый cutoff weight для подтверждения поддельного блока — им не хватит суммарного веса даже если все скомпрометированные валидаторы будут действовать согласованно.

Это свойство обеспечивает cryptographic safety: даже если треть сети контролируется атакующими, честное большинство (≥2/3) сохраняет контроль над консенсусом.

TransactionChecker и Merkle Proofs

TransactionChecker — это специализированный контракт верификации, выполняющий криптографическую проверку того, что конкретная транзакция была включена в определённый блок, и этот блок был подписан достаточным количеством валидаторов.

Механизм работает на основе Merkle proofs — математических структур данных, позволяющих эффективно доказать включение элемента в набор без необходимости передавать весь набор. В контексте блокчейна: можно доказать, что транзакция находится в блоке, не передавая все транзакции блока.

Алгоритм верификации (пошаговый):

  1. Инициация проверки: Event-контракт вызывает check_transaction() на TransactionChecker, передавая:

    • Адрес аккаунта, выполнившего транзакцию
    • Логическое время (lt) транзакции
    • Закодированное доказательство (proof data)
  2. Декодирование proof структуры: TransactionChecker разбирает proof data, извлекая:

    • tx_proof — Merkle proof, связывающий транзакцию с блоком (цепочка хешей от транзакции до корня Merkle tree блока)
    • block_proof — Merkle proof блока (доказательство, что блок принадлежит мастерчейну)
    • signatures — коллекция подписей валидаторов для этого блока (validator_index → signature)
  3. Верификация транзакции в блоке: TransactionChecker вызывает lookup_tx_in_block():

    • Проверяет Merkle path от хеша транзакции к корню блока
    • Верифицирует, что hash(transaction) ∈ block.transactions_root через последовательность хешей
    • Извлекает хеш блока (block_hash) для дальнейшей верификации
  4. Делегирование проверки подписей: TransactionChecker отправляет check_block() запрос в LiteClient с:

    • block_hash — хеш блока для проверки
    • block_proof — доказательство блока
    • signatures — коллекция подписей валидаторов
  5. Верификация подписей в LiteClient: LiteClient выполняет критическую проверку:

    • Итерируется по коллекции signatures
    • Для каждой подписи:
      • Извлекает validator_index и signature
      • Получает pubkey и weight валидатора из current_validators_set[validator_index]
      • Вызывает ed25519_check_signature(block_hash, signature, pubkey)
      • При успехе: total_signed_weight += weight
    • Финальная проверка: total_signed_weight >= cutoff_weight
  6. Подтверждение верификации: При успешной проверке:

    • LiteClient отправляет обратный вызов с результатом верификации
    • TransactionChecker получает подтверждение
    • TransactionChecker отправляет response::transaction_checked Event-контракту
    • Event-контракт обновляет статус и продолжает обработку трансфера

Защита от атак

Система реализует многоуровневую защиту от различных векторов атак:

АтакаЗащитный механизм
Double-spendingАдрес Event-контракта детерминированно вычисляется из msgHash. Повторный деплой контракта с идентичным адресом физически невозможен в TVM.
Replay attackEventConfiguration верифицирует chainId и destinationChainId — событие из одной сети не может быть применено в другой.
Forged proofsMerkle proof верифицируется криптографически. Подделка математически невозможна без знания приватных ключей валидаторов.
Invalid signaturesLiteClient проверяет, что суммарный вес подписей ≥ 2/3 + 1 от общего веса.

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

On-chain компоненты (Смарт-контракты)

LiteClient

Контракт легкого клиента, хранящий информацию о ключевых блоках другой сети.

Хранимые данные:

  • current_seq_no — номер последовательности текущего ключевого блока
  • current_epoch_since/until — временные метки начала/окончания эпохи валидаторов
  • current_cutoff_weight — минимальный вес подписей (2/3 + 1 от общего веса валидаторов)
  • current_validators_set — набор валидаторов с публичными ключами и весами

Операции:

  • new_key_block — обработка нового ключевого блока: верификация подписей, обновление набора валидаторов
  • check_block — проверка подписей блока против текущего набора валидаторов

TransactionChecker

Контракт для верификации транзакций из другой сети через Merkle proofs.

Операции:

  • check_transaction — проверка транзакции:
    1. Извлекает Merkle proof транзакции и блока
    2. Проверяет, что транзакция существует в блоке
    3. Отправляет запрос в LiteClient для верификации подписей блока
    4. При успешной верификации отправляет response::transaction_checked

ProxyMultiVaultNative (NativeProxy)

Proxy-контракт для работы с native токенами (jettons).

Основные функции:

  • Принимает native токены (lock) при исходящих трансферах
  • Отправляет native токены (unlock) при входящих трансферах
  • Эмитит события для трансферов в другие сети
  • Управляет комиссиями и дневными лимитами

Ключевые методы:

  • transferNotification — callback при получении jetton-токенов, инициирует исходящий трансфер
  • onTvmEventConfirmedExtended — обработка подтверждённого события, завершение входящего трансфера

ProxyMultiVaultAlien (AlienProxy)

Proxy-контракт для работы с alien токенами.

Основные функции:

  • Минтит alien токены при входящих трансферах
  • Обрабатывает callback после сжигания alien токенов и инициирует исходящий трансфер
  • Управляет деплоем новых alien токенов
  • Работает с MergePool/MergeRouter для объединения токенов

Ключевые методы:

  • onTvmEventConfirmedExtended — минтинг alien токенов при входящем трансфере
  • onAcceptTokensBurn — callback от jetton-контракта после сжигания токенов
  • deployTvmAlienToken — деплой нового alien токена

EventConfiguration (TvmTvmEventConfiguration)

Контракт конфигурации событий, управляющий деплоем event-контрактов.

Хранимые данные:

  • Адрес TransactionChecker
  • Код event-контракта
  • Адрес proxy-контракта
  • Параметры конфигурации (chainId, startTimestamp, endTimestamp)

Ключевые методы:

  • deployEvent — деплой нового event-контракта для обработки входящего трансфера
  • deriveEventAddress — вычисление детерминированного адреса Event-контракта из msgHash
  • onTvmEventConfirmedExtended — callback от Event, проксирует вызов на Proxy

MultiVaultTvmTvmEvent (Alien / Native)

Event-контракты для обработки конкретных трансферов.

Ключевые методы:

  • processProof — обработка proof транзакции, вызов TransactionChecker
  • onTrustlessVerify — callback от TransactionChecker при успешной верификации
  • _onConfirm — вызов proxy для завершения трансфера

MergePool / MergeRouter

Контракты для объединения alien токенов из разных сетей в единое представление (canon token). Например, USDT переведённый из TON и USDT переведённый из Ethereum могут быть объединены в один canon USDT.

MergeRouter:

  • Роутинг к соответствующему MergePool для токена

MergePool:

  • Хранит маппинг derive-токенов к canon-токену
  • Конвертация между decimals разных представлений

Off-chain компоненты (Backend)

Sync Service

Фоновый сервис синхронизации ключевых блоков между сетями.

Важно

Sync Service работает в фоновом режиме и синхронизирует ключевые блоки периодически, а не для каждого трансфера. Это необходимо для поддержания актуального набора валидаторов в LiteClient.

Функции:

  • Отслеживает ключевые блоки в сети отправления
  • Загружает актуальную информацию о validator set в контракт LiteClient сети назначения
  • Вызывает new_key_block на LiteClient для обновления набора валидаторов

Частота обновлений:

  • Key blocks появляются при смене эпох валидаторов
  • Обычно 1-2 раза в сутки (зависит от сети)

Proof API

Легкая нода, синхронизирующая блоки и предоставляющая API для построения proof chain.

Функции:

  • Синхронизирует все блоки в реальном времени
  • Формирует Merkle tree proof для транзакции
  • Формирует proof блока
  • Endpoint: GET /v1/proof_chain/{address}/{lt} — возвращает BOC с proof chain

Bridge API

Индексатор событий для конкретной TVM сети.

Функции:

  • Индексация событий из proxy-контрактов
  • Отслеживание статусов трансферов
  • Предоставление данных для деплоя event-контрактов

Особенность: Один инстанс Bridge API обслуживает одну TVM сеть.

Bridge Aggregator API

Агрегатор над всеми API для работы с трансферами.

Функции:

  • Подготовка payload для трансферов
  • Объединение истории трансферов из всех сетей
  • Отслеживание статусов трансферов независимо от сетей

Ключевые endpoints:

  • POST /payload/build — построить payload для транзакции трансфера
  • POST /transfers/search — поиск трансферов с фильтрацией
  • POST /transfers/status — получить статус конкретного трансфера

Жизненный цикл Event-контракта

Статусы Event-контракта

КодСтатусОписание
0InitializingНачальное состояние после деплоя
1PendingОжидание верификации через TransactionChecker
2ConfirmedТрансфер подтверждён, proxy вызван, токены доставлены
3RejectedТрансфер отклонён (верификация провалена)
4CancelledТрансфер отменён пользователем
5LimitReachedПревышен дневной лимит, ожидает одобрения
6LiquidityRequestedЗапрошена ликвидность от провайдеров
7LiquidityProvidedЛиквидность предоставлена
8VerifiedТранзакция верифицирована (trustless), но токены ещё не доставлены

Диаграмма переходов

Основной поток (успешный трансфер)

  1. Initializing — EventConfiguration деплоит контракт, вызывает processProof()
  2. Pending — Event отправляет verifyTx() в TransactionChecker, ожидает ответа
  3. Verified — TransactionChecker подтвердил транзакцию через onTrustlessVerify(true)
  4. Confirmed — Event вызвал _onConfirm(), Proxy выполнил mint/unlock

Edge Cases

LimitReached (превышен дневной лимит)

Когда сумма трансфера превышает дневной лимит:

  1. Proxy вызывает Event.dailyLimitReached(limitApprover)
  2. Статус → LimitReached
  3. limitApprover может:
    • approveLimit() → продолжить трансфер → Confirmed
    • rejectLimit() → отклонить → Rejected
  4. Пользователь может: cancel()Cancelled (обратный трансфер)

LiquidityRequested (недостаточно ликвидности)

Когда NativeProxy не может unlock токены (недостаточно баланса):

  1. NativeProxy вызывает Event.notEnoughLiquidity()
  2. Статус → LiquidityRequested
  3. Event запрашивает eventTokenWallet для приёма ликвидности
  4. Провайдер ликвидности может отправить токены с bounty
  5. После получения → LiquidityProvided → токены доставлены пользователю
  6. Или пользователь может: cancel()Cancelled (обратный трансфер)

Bounty для провайдера

Провайдер ликвидности получает bounty — вознаграждение от пользователя за предоставление ликвидности. Размер bounty устанавливается пользователем или sender'ом при инициации трансфера.

Потоки трансферов

Lock Native → Mint Alien

Этот поток описывает перевод native токена из сети отправления в сеть назначения, где он становится alien токеном.

Пошаговое описание

Шаг 1-2: Инициация и блокировка

Пользователь отправляет jetton-токены на NativeProxy. В payload указывается адрес получателя и целевая сеть. Proxy блокирует токены и эмитит событие TvmTvmNative.

Шаг 3: Деплой Event-контракта

Proof API генерирует Merkle proof транзакции. EventConfiguration деплоит event-контракт с данными proof в сети назначения.

Шаг 4-5: Верификация

Event-контракт вызывает TransactionChecker для верификации транзакции. TransactionChecker проверяет Merkle proof и запрашивает LiteClient для верификации подписей блока.

Шаг 6-7: Подтверждение

При успешной верификации TransactionChecker вызывает onTrustlessVerify(true) на Event-контракте. Статус меняется на Verified. Затем Event-контракт вызывает _onConfirm(), который:

  • Меняет статус на Confirmed
  • Отправляет onTvmEventConfirmedExtended в AlienProxy

Шаг 8-9: Минтинг

AlienProxy получает подтверждение, проверяет лимиты, взимает комиссию и минтит alien-токены получателю.


Burn Alien → Unlock Native

Обратный поток: возврат alien токена в исходную сеть, где разблокируются native токены.

Пошаговое описание

Шаг 1-2: Пользователь сжигает alien токены через AlienProxy. Proxy эмитит событие TvmTvmAlien.

Шаг 3-5: Деплой Event-контракта и верификация аналогично предыдущему потоку.

Шаг 6-7: Event-контракт получает подтверждение, статус меняется Verified → Confirmed.

Шаг 8-9: NativeProxy получает подтверждение и разлокивает (unlock) native токены получателю.

Edge Case: Недостаточно ликвидности

Если баланс wallet NativeProxy недостаточен для unlock:

  1. NativeProxy вызывает Event.notEnoughLiquidity()
  2. Event → статус LiquidityRequested
  3. Провайдер ликвидности может отправить токены с bounty
  4. Или пользователь может отменить трансфер через cancel()

Lock Native → Unlock Native

Поток для трансфера native токена между сетями, где в обеих сетях токен является native.

Особенность реализации

Трансфер технически выполняется через Alien-поток, но на AlienProxy происходит проверка: если для токена настроен native-native сценарий (есть запись в predeployedTokens), то AlienProxy не минтит токен, а проксирует вызов на NativeProxy.

Пошаговое описание

Шаг 1-2: Пользователь отправляет native токены на NativeProxy в сети отправления. Токены блокируются, эмитится событие TvmTvmNative.

Шаг 3-5: В сети назначения деплоится MultiVaultTvmTvmEventAlien (не Native!) через AlienEventConfiguration. Происходит верификация через TransactionChecker.

Шаг 6-7: Event-контракт вызывает receivePredeployedToken на AlienProxy. Если токен зарегистрирован в predeployedTokens, возвращается PredeployedTokenData с адресом nativeProxyTokenWallet.

Шаг 8-9: После верификации Event-контракт вызывает onTvmEventConfirmedExtended на AlienProxy, передавая nativeProxyTokenWallet в метаданных.

Шаг 10: AlienProxy проверяет nativeProxyTokenWallet.hasValue(). Если true — не минтит, а проксирует вызов на NativeProxy через proxyMultiVaultNative.onTvmEventConfirmedExtended().

Шаг 11: NativeProxy получает вызов (принимает от AlienProxy или напрямую от EventConfig), разблокирует native токены и отправляет получателю.

Когда используется этот поток?

Lock Native → Unlock Native используется когда токен настроен как native в обеих сетях через predeployedTokens в AlienProxy. Это возможно для:

  • Wrapped native токенов (например, wTON)
  • Токенов, специально настроенных администратором

Настройка происходит через регистрацию PredeployedTokenData в маппинге tvmConfiguration.predeployedTokens.

Риски и защитные механизмы

РискПричинаЗащитный механизм
Double-spendingПовторная обработка той же транзакцииАдрес Event-контракта детерминированно вычисляется из msgHash. Повторный деплой невозможен.
Forged Merkle proofПодделка proof транзакцииMerkle proof верифицируется криптографически через extract_merkle_proof() и lookup_tx_in_block()
Invalid block signaturesНедостаточно подписей или подписи неверныLiteClient проверяет: суммарный вес подписавших ≥ cutoff_weight (2/3 + 1)
Outdated validator setLiteClient хранит устаревший набор валидаторовSync Service периодически обновляет validator set через new_key_block()
Replay attackEvent из одной сети обрабатывается в другойEventConfiguration проверяет chainId в proof == networkConfiguration.chainId
Wrong destination chainEvent предназначен для другой сетиEventConfiguration проверяет destinationChainId
Unauthorized event emitterСобытие эмитировано не Proxy-контрактомEventConfiguration проверяет accountAddr == eventEmitter
Daily limit exceededПревышен дневной лимит трансфераProxy проверяет лимиты; при превышении → статус LimitReached, ожидает одобрения
Not enough liquidityNativeProxy не может unlock токеныNativeProxy вызывает notEnoughLiquidity(); провайдер может предоставить ликвидность с bounty
Wrong predeployed tokenНеверный externalNativeProxyWalletEvent проверяет соответствие с данными из predeployedTokens

Что делать при проблемах с трансфером?

  1. LimitReached — дождитесь одобрения от limitApprover или отмените трансфер
  2. LiquidityRequested — дождитесь провайдера ликвидности или отмените трансфер (получите обратный трансфер в сеть отправления)
  3. Cancelled — токены будут возвращены в сеть отправления через обратный трансфер

Ошибки смарт-контрактов

Event-контракты

Ошибки Event-контрактов (MultiVaultTvmTvmEventAlien, MultiVaultTvmTvmEventNative):

КодУсловие
2321Неверный статус для processProof(): status != Initializing && status != Pending && status != Verified
2313Вызов не от EventConfiguration: msg.sender != eventInitData.configuration
2329Callback не от TransactionChecker: msg.sender != transactionChecker
2312Неверный статус для onTrustlessVerify(): status != Pending
2901Callback не от Proxy: msg.sender != transitionalData.proxy
2330Неверный externalNativeProxyWallet для predeployed token
2326Callback не от TokenRoot: msg.sender != transitionalData.token
2327Callback не от MergeRouter: msg.sender != transitionalData.router
2328Callback не от MergePool: msg.sender != transitionalData.pool
2335Вызов не от limitApprover: msg.sender != limitApprover
2332Вызов не от recipient/sender (для cancel/setBounty)
2324Неверный статус для операции (approveLimit, rejectLimit, cancel, setBounty, retry)
2333Bounty превышает amount: bounty > eventData.amount
2334Callback не от eventTokenWallet: msg.sender != eventTokenWallet
2331Callback не от Proxy (Native Event) или не от proxy/native_proxy (Alien Event)

EventConfiguration

Ошибки контракта TvmTvmEventConfiguration:

КодУсловие
2218endTimestamp уже установлен: networkConfiguration.endTimestamp != 0
2216endTimestamp меньше startTimestamp
2221Proof из другой сети: chainId != networkConfiguration.chainId
2222Неверный msgHash: tvm.hash(message) != _eventVoteData.msgHash
2223Событие не для целевой сети: destinationChainId != TON_GLOBAL_ID
2220Событие не от Proxy: accountAddr != eventEmitter.value
2211Событие раньше startTimestamp: txTimestamp < networkConfiguration.startTimestamp
2215Событие позже endTimestamp (если endTimestamp != 0)
2212Callback не от Event-контракта: deriveEventAddress(_eventInitData) != msg.sender

Proxy-контракты

Ошибки контрактов ProxyMultiVaultAlien и ProxyMultiVaultNative:

КодУсловие
2710Callback не от разрешённой EventConfiguration: конфигурация отсутствует в tvmConfiguration.incomingConfigurations

TransactionChecker

Ошибки контракта TransactionChecker:

КодУсловие
200Транзакция не найдена в блоке
201Неверный хеш транзакции
202Блок не является masterchain блоком
203Callback не от LiteClient: sender_address != ctx_lite_client_addr

LiteClient

Ошибки контракта LiteClient:

КодУсловие
111Блок не является key block
112Key block из той же эпохи
113Key block из старой эпохи
114Неверная подпись валидатора
115Недостаточный вес подписей: total_signed_weight < ctx_current_cutoff_weight
116Некорректные параметры эпохи валидаторов

Общие ошибки Merkle Proof

КодУсловие
101Cell не является exotic cell
102Cell не является Merkle proof
103Cell не является Merkle update

ChainConnect Bridge Documentation