Jetton Pattern: эталон шардированного токена
Проблема: ERC-20 не масштабируется
На Ethereum, ERC-20 хранит все балансы в одном контракте:
// Ethereum ERC-20 — монолитный
contract Token {
mapping(address => uint256) balances; // ВСЕ пользователи здесь
function transfer(to, amount) {
balances[msg.sender] -= amount;
balances[to] += amount;
}
}
На Ethereum это нормально (нет шардирования). На TON — bottleneck.
Решение: Jetton = Master + N Wallets
Jetton Standard разделяет state:
Transfer Flow: 3 сообщения
Перевод 100 tokens от Alice к Bob:
Шаг 1: Alice → Alice's Wallet: "transfer(100, Bob)"
Alice's Wallet:
- Проверить: owner == Alice? [OK]
- Проверить: balance >= 100? [OK]
- balance -= 100 (Alice: 500 → 400)
- Вычислить адрес Bob's Wallet: hash(wallet_code + init_data(Bob, master))
- Отправить internal_transfer(100, Alice) → Bob's Wallet
Шаг 2: Alice's Wallet → Bob's Wallet: "internal_transfer(100, from=Alice)"
Bob's Wallet:
- Проверить: sender == valid Jetton Wallet? (code hash verification)
- balance += 100 (Bob: 300 → 400)
- Если Bob's Wallet не существовал — deploy (init_code in message)
- Отправить transfer_notification(100, Alice) → Bob
Шаг 3: Bob's Wallet → Bob: "transfer_notification(100, from=Alice)"
Bob (может быть контракт или кошелёк):
- Получает уведомление: "вам перевели 100 tokens от Alice"
- Может обработать: например, DEX обработает swap
Почему deploy при первом получении?
Если Bob никогда не получал этот токен — его Wallet-контракт не существует. Sender (Alice’s Wallet) включает state_init в сообщение — это деплоит Bob’s Wallet автоматически. TON достаточно умён, чтобы проигнорировать state_init, если контракт уже задеплоен.
Канонические Jetton-стандарты и эталонные реализации
“Jetton 2.0” — это маркетинговое название, не отдельный стандарт. На практике production Jetton-контракт собирается из нескольких канонических TEP’ов:
| Стандарт | Что описывает | Реальность 2025-2026 |
|---|---|---|
| TEP-74 | Базовый Jetton (Master + Wallet, transfer, internal_transfer) | Обязательная база. Все Jetton’ы реализуют TEP-74. |
| TEP-89 | Discoverable Wallets (provide_wallet_address → take_wallet_address) | Стало де-факто обязательным: индексеры и DEX полагаются на on-chain discovery, без TEP-89 интеграция ломается. |
| TEP-177 | Mintless Jettons (Merkle airdrop, claim прямо в Wallet) | Используется массово в airdrop-проектах (DOGS, NotPixel, HMSTR) — claim без предварительного minting миллионам пользователей. |
Эталонные репозитории, на которые стоит ориентироваться:
| Репозиторий | Назначение |
|---|---|
ton-blockchain/stablecoin-contract | Canonical reference Jetton (TEP-74 + TEP-89), реальная база для USDT-style стейблкоинов |
ton-community/mintless-jetton | Reference impl TEP-177 (TEP-74 + TEP-89 совместимый) |
EmelyanenkoK/modern_jetton | Gas-оптимизированный variant с улучшенной логикой forward-payload |
Что реально стоит за “оптимизациями”
Когда в маркетинге говорят про “ускоренный Jetton” — обычно имеют в виду одно из двух: (1) переход на mintless схему (TEP-177), убирающую массовый pre-mint и снижающий нагрузку на сеть, или (2) обновлённый wallet code с оптимизированной gas-логикой (как в stablecoin-contract или modern_jetton). Базовый transfer flow остаётся 3-сообщенческим, как и в TEP-74.
Security: как Wallet верифицирует sender?
Проблема: подделка internal_transfer
Злоумышленник может попытаться отправить internal_transfer(1000000, fake) напрямую в Bob’s Wallet, чтобы зачислить себе токены.
Решение: Sender Address Verification
Bob's Wallet получает internal_transfer от sender_address:
1. Прочитать claimed_from из body (кто якобы отправил)
2. Вычислить: expected_sender = hash(wallet_code + init_data(claimed_from, master))
3. Проверить: sender_address == expected_sender?
4. Если нет — отклонить! (Sender не является легитимным Wallet)
Deterministic addresses = trustless verification
Wallet не хранит whitelist допустимых отправителей. Он вычисляет ожидаемый адрес sender-а из claimed data. Если вычисленный адрес != actual sender — сообщение поддельное. Это O(1) verification без storage overhead.
Design Insights для собственных контрактов
Jetton pattern — template для любого sharded state:
| Jetton | Ваш контракт |
|---|---|
| Master = metadata + total_supply | Master = global config |
| Wallet = per-user balance | Child = per-user/per-entity state |
| transfer = wallet→wallet | operation = child→child |
| internal_transfer = verified msg | verified_operation = code hash check |
Применяйте этот паттерн к:
- NFT Collection: Collection (master) + Item (child per NFT)
- Staking Pool: Pool (master) + Position (child per staker)
- DEX: Pool (master) + LP Wallet (child per liquidity provider)
- Voting: Proposal (master) + Vote (child per voter)