К основному содержанию
T TON Adoption
Основы GUIDE · 2026

TEP-74: стандарт jetton в TON — технический разбор

Подробный разбор TEP-74: master + wallet, transfer-сообщение, forward-комиссии, mint/burn, get-методы, отличия от ERC-20 и место в семействе TEP.

Автор
TON Adoption Team · исследовательская группа проекта
Опубликовано
6 мин. чтения

TEP-74 — это технический документ, который описывает интерфейс jetton-токенов в TON. Если вы видите в кошельке USDT, NOT, STON, hTON или любой другой токен «не TON» — почти наверняка под капотом работает именно TEP-74. В этой статье мы разберём, как устроен стандарт, чем jetton принципиально отличается от ERC-20, что именно стандартизирует TEP-74 (а что — нет), и стоит ли писать свой контракт с нуля или брать готовую референсную имплементацию.

Материал рассчитан на разработчиков, готовящихся к запуску собственного jetton, и на любопытных пользователей, которым важно понимать, что происходит, когда они нажимают «Отправить USDT».

Что такое TEP и откуда он берётся

TEP — TON Enhancement Proposal, по аналогии с EIP (Ethereum) и BIP (Bitcoin). Это формализованные предложения по стандартизации интерфейсов, форматов данных и поведения контрактов. Список ведётся в репозитории ton-blockchain/TEPs на GitHub. Принятие TEP — open-source процесс: предложение публикуется, обсуждается, дорабатывается и в какой-то момент маркируется как Final, если стало де-факто стандартом.

Семейство TEP, связанных с токенами и NFT, выглядит так:

TEPО чёмСтатус
TEP-62NFT standard (item + collection)Final
TEP-64Token metadata (on-chain / off-chain)Final
TEP-66NFT royalty standardFinal
TEP-74Jetton standard (master + wallet)Final
TEP-85SBT — Soul-Bound TokenFinal
TEP-89Discoverable jettons (Jetton-89)Final

TEP-74 финализирован в 2022 году и с тех пор остаётся базовым интерфейсом для всех «обычных» токенов в TON. TEP-89 — расширение поверх TEP-74, добавляющее get-метод get_wallet_address, который позволяет кошелькам и эксплорерам детерминированно вычислять адрес jetton-wallet получателя без сканирования всей сети.

Master + wallet: главное архитектурное решение

В Ethereum контракт ERC-20 — один. Внутри него таблица mapping(address => uint256) balances. Когда Алиса отправляет 100 USDT Бобу, она вызывает transfer() у этого единственного контракта, и он обновляет две ячейки таблицы.

В TON архитектура другая. У каждого jetton есть master-контракт (его иногда называют minter) и отдельный jetton-wallet для каждого держателя. То есть для USDT-jetton на TON существует один master и десятки миллионов jetton-wallet — по одному на каждый адрес, который когда-либо держал USDT.

Когда Алиса отправляет 100 USDT Бобу, происходит следующее:

  1. Алиса отправляет сообщение transfer в свой USDT jetton-wallet.
  2. Её jetton-wallet списывает 100 USDT с локального баланса и отправляет внутреннее сообщение internal_transfer в jetton-wallet Боба.
  3. Jetton-wallet Боба, получив сообщение, увеличивает свой локальный баланс на 100 и отправляет уведомление transfer_notification на адрес Боба (его обычный TON-кошелёк).
  4. Излишки газа возвращаются Алисе через excess-сообщение.

Master-контракт в самой цепочке transfer не участвует. Он нужен только для эмиссии (mint), сжигания и хранения метаданных. Это критично: транзакции jetton параллелизуемы, потому что не упираются в один контракт-горлышко.

Зачем такое усложнение

Идея отдельного wallet-контракта на каждого держателя выглядит избыточно — пока вы не вспомните, что TON шардится. Когда нагрузка на сеть растёт, шарды могут разделяться. Если бы все балансы USDT лежали в одном контракте, этот контракт оказался бы в одном шарде, и пропускная способность USDT-транзакций упёрлась бы в пропускную способность одного шарда. С отдельными wallet-контрактами балансы Алисы и Боба могут оказаться в разных шардах, и их транзакции обрабатываются параллельно.

Расплата: отправитель платит за газ двух контрактов (своего wallet + wallet получателя), плюс forward fee на внутреннее сообщение. На практике одна transfer-операция стоит 0.03-0.05 TON, тогда как в Ethereum это $0.5-3 в зависимости от gas price. В пересчёте на доллары TON выигрывает почти всегда.

Структура transfer-сообщения

TEP-74 фиксирует op-коды и формат TL-B-схемы. Ключевые операции:

  • 0x0f8a7ea5 — transfer (внешний, от пользователя)
  • 0x178d4519 — internal_transfer (между двумя jetton-wallet)
  • 0x7362d09c — transfer_notification (от wallet получателя владельцу)
  • 0xd53276db — excesses (возврат излишков газа)
  • 0x595f07bc — burn (сжигание)
  • 0x178d4519 — internal mint (от master к wallet при эмиссии)

Внешний transfer от пользователя содержит: query_id, amount (сколько токенов отправить), destination (TON-адрес получателя — не jetton-wallet, а его обычный кошелёк), response_destination (куда вернуть излишки), custom_payload, forward_ton_amount (сколько TON приложить к уведомлению получателю), forward_payload (произвольные данные, которые dApp получателя сможет прочитать).

Поле forward_payload критично для DEX и DeFi: именно через него STON.fi или DeDust получают команду «обменять эти 100 USDT на TON», когда пользователь отправляет jetton на адрес роутера.

Get-методы: чтение состояния без газа

TEP-74 требует два get-метода:

get_jetton_data() на master-контракте возвращает: total_supply, mintable-флаг, admin_address, jetton_content (cell с метаданными по TEP-64), jetton_wallet_code (код, по которому детерминированно вычисляются адреса всех wallet).

get_wallet_data() на jetton-wallet возвращает: balance, owner_address, jetton (адрес master), jetton_wallet_code.

Из этой пары следует важное свойство: зная адрес owner и адрес master, любой клиент может локально (без обращения к сети) вычислить адрес соответствующего jetton-wallet. Именно так Tonkeeper, MyTonWallet и эксплореры показывают балансы по всем jetton — они не сканируют всю сеть, а просто берут известный список master-адресов и считают адрес wallet для текущего пользователя.

TEP-89 добавляет к этому get-метод get_wallet_address(owner) на master-контракте — для случаев, когда клиент по каким-то причинам не хочет повторять вычисление сам.

Mint и burn

Эмиссия jetton — это сообщение от master к адресу будущего держателя. Master создаёт jetton-wallet (если его ещё нет) и отправляет ему internal_transfer с увеличением баланса. По TEP-74 mint-операция не имеет фиксированного op-кода — это намеренно: эмитент может реализовать любую логику доступа (один admin, multisig, governance-голосование, vesting).

Burn (op 0x595f07bc) — это сообщение от пользователя в свой jetton-wallet. Wallet списывает баланс и отправляет master сообщение burn_notification, чтобы тот уменьшил total_supply. Burn нужен в первую очередь для bridge-сценариев: чтобы вывести USDT с TON на Ethereum, USDT-jetton сжигается на TON, а bridge выдаёт эквивалент на другой сети.

Что TEP-74 НЕ стандартизирует

Это, пожалуй, самая важная часть разбора. TEP-74 описывает только базовый интерфейс. Всё, что выходит за его пределы, — на усмотрение эмитента:

  • Pause / freeze. В стандарте нет ни pause, ни freeze. Но USDT-jetton от Tether это умеет — потому что эмитент дописал в код возможность для admin-адреса заморозить любой wallet. У сообщества это вызывает споры, но это легально в рамках TEP-74.
  • Blacklist. Аналогично — добавляется поверх стандарта.
  • Upgrade. Контракт может быть upgradeable (set_code) или иммутабельным — TEP-74 не диктует. Tether-jetton upgradeable, большинство community-токенов — нет.
  • Royalty / transfer fee. Можно реализовать комиссию на transfer, но это нестандартно и почти все экосистемные инструменты её не учтут.
  • Metadata stability. TEP-64 позволяет хранить метаданные off-chain (IPFS, HTTPS) — но никаких гарантий, что хостинг переживёт эмитента, стандарт не даёт.

Jetton vs ERC-20: краткая сравнительная таблица

ПараметрERC-20Jetton (TEP-74)
Контрактов на токен11 master + N wallet
Стоимость transferсредняя газа за storage writeгаз двух контрактов + forward
Параллелизмнет, всё в одном контрактеда, балансы в разных шардах
Чтение балансаbalanceOf(addr) view-callget-метод на детерминированном адресе
Approve / allowanceданет (заменяется forward_payload)
Стандарт заморозкинет (зависит от реализации)нет (зависит от реализации)
Финальность~12-15 блоков для PoS~5 секунд masterchain

Отсутствие approve — отдельная тема. В Ethereum DEX требует от пользователя сначала approve, потом swap. В TON это одна транзакция: пользователь отправляет jetton прямо роутеру DEX, а в forward_payload кладёт команду swap. Это и проще, и безопаснее — нет вечных allowance, которые регулярно эксплуатируют drainer-сайты.

Стоит ли писать TEP-74-контракт с нуля

В подавляющем большинстве случаев — нет. Есть три практичных пути:

  1. Референсная имплементация от TON Foundation на FunC — самый консервативный выбор. Код прошёл много аудитов, используется в подавляющем большинстве jetton.
  2. Tact — современный язык, jetton-шаблон идёт в стандартной библиотеке @ton-community/jetton. Подходит, если команда не хочет погружаться в FunC.
  3. Tolk — новейший язык TON, тоже имеет готовый jetton-шаблон. Производительнее FunC, читается проще.

Писать с нуля стоит только если нужна нестандартная логика: vesting, rebasing, on-chain governance с динамическим supply. И в этом случае стоит закладывать бюджет на 2-3 независимых аудита — баги в jetton-контрактах чаще всего необратимы.

Чек-лист перед запуском собственного jetton

  • Метаданные по TEP-64: name, symbol, decimals (для TON-jetton обычно 9), description, image. Хостить на IPFS или хотя бы на собственном CDN.
  • Список mint-операций определён: разовая эмиссия, vesting, mint by governance.
  • Решено, нужны ли admin-полномочия (freeze, upgrade) — и публично задокументировано.
  • TEP-89 реализован, чтобы кошельки и эксплореры быстро находили wallet-адреса.
  • Контракт верифицирован на Tonviewer / tonscan — иначе пользователи не увидят исходники.
  • Подключены индексаторы (DTON, TON API) для быстрой работы DEX-агрегаторов.

Что читать дальше

Стандарт лучше всего изучать в связке с архитектурой сети. Если ещё не разобрались, как именно TON параллелит транзакции по шардам — переходите к материалу про шардирование. Если интересуют сами языки контрактов — есть отдельные гайды по FunC vs Tact и по Tolk. А пользовательскую сторону jetton (как добавить кастомный токен в кошелёк, почему адреса разных wallet выглядят так похоже) разбираем в обзоре jetton для начинающих.

Частые вопросы

У ERC-20 один контракт хранит балансы всех держателей. У jetton каждый держатель имеет свой собственный smart-контракт-кошелёк, который ссылается на master-контракт. Это дороже на стороне отправителя, но даёт горизонтальную масштабируемость и параллельную обработку транзакций.
Заморозку, blacklist, паузу и upgrade-логику. Эти возможности — на усмотрение эмитента. Поэтому у USDT-jetton от Tether есть freeze authority, а у обычного community-jetton — нет.
Нет. Для большинства задач хватает референсной имплементации от TON Foundation или готовых helpers в Tact/Tolk. Писать с нуля имеет смысл только если нужна нестандартная логика — vesting, rebasing, ребейз-механика.
Около 0.03-0.05 TON на одну операцию transfer. Часть уходит в forward fee на сообщение jetton-wallet получателя; излишки возвращаются отправителю через response_destination.

Похожие материалы