Jetton vs ERC-20

Сравнение Jetton и ERC-20: архитектура балансов, transfer flow и что это значит для клиента и контракта.

Jetton vs ERC-20 — коротко

ERC-20 хранит все балансы в одном контракте. Jetton — master + jetton-wallet на каждого владельца: перевод идёт сообщением на wallet отправителя, а не вызовом transfer на едином токене. Для клиента на TON почти всегда нужен адрес jetton-wallet, а не только master.


Таблица сравнения

ПараметрJetton (TON)ERC-20 (Ethereum)
Где балансОтдельный jetton-wallet контрактmapping(address => uint) в токене
TransferСообщение на wallet отправителяtoken.transfer(to, amount)
Discover walletВычисляется от master + ownerНе нужен — один адрес токена
Approve / allowanceНет в базовом стандарте (другие паттерны)approve + transferFrom
Gas / нагрузкаРаспределена по шардамКонцентрируется на одном контракте
СобытияOn-chain сообщения + индексаторыTransfer / Approval logs

Когда важна модель Jetton

  • Пишешь депозит в vault/DEX: принимаешь входящее сообщение от jetton-wallet, проверяешь sender
  • Показываешь баланс в UI: сначала находишь wallet address, потом читаешь get_wallet_data
  • Делаешь batch-отправки — учитываешь отдельный gas на каждое сообщение wallet→wallet

Когда привычка ERC-20 ломает код

  • Вызываешь «transfer на master» как на ERC-20 — master так не переводит баланс пользователя
  • Ждёшь allowance из коробки — в TEP-74 этого нет
  • Считаешь адрес master «адресом токена пользователя» для UI баланса

Пример: куда слать transfer

typescript
// @ton/core ^0.27 — body для Jetton transfer (TEP-74)
import { Address, beginCell, toNano } from "@ton/core";

const JETTON_TRANSFER = 0xf8a7ea5;

function buildJettonTransfer(opts: {
  to: Address;
  amount: bigint;
  responseTo: Address;
  forwardTon: bigint;
}) {
  return beginCell()
    .storeUint(JETTON_TRANSFER, 32)
    .storeUint(0n, 64) // query_id
    .storeCoins(opts.amount)
    .storeAddress(opts.to)
    .storeAddress(opts.responseTo)
    .storeBit(false) // no custom payload
    .storeCoins(opts.forwardTon)
    .storeBit(false) // no forward_payload
    .endCell();
}

// Важно: send → jettonWallet пользователя, не jetton master
await userJettonWallet.send(
  sender,
  { value: toNano("0.05") },
  buildJettonTransfer({
    to: recipient,
    amount: 1_000_000n,
    responseTo: userAddress,
    forwardTon: toNano("0.01"),
  }),
);

Master нужен для mint/metadata и вычисления адреса wallet. Баланс и transfer — всегда через jetton-wallet.

Материалы gramdocs.tech носят образовательный характер и не являются финансовой, юридической или инвестиционной рекомендацией. Работа с блокчейном TON и токеном Gram связана с рисками потери средств. Правовая информация