Learning Platform
Глоссарий Troubleshooting
Урок 05.04 · 15 мин
Продвинутый
Deterministic AddressState InitContract DiscoveryVerification

Deterministic Addresses и Contract Discovery

Проблема: как найти контракт?

На Ethereum: вы вызываете token.balanceOf(alice) — контракт хранит mapping. На TON: балансы в отдельных контрактах. Как найти контракт, хранящий баланс Alice?

Решение: Deterministic Address Computation

Адрес контракта на TON = hash(workchain_id + state_init), где state_init = code + initial_data.

Формула:
address = hash(
  workchain: 0,                        // Workchain 0
  state_init: {
    code: jetton_wallet_code,           // Bytecode кошелька
    data: initial_data(owner, master)   // Начальные данные
  }
)

Если мы знаем:
  - jetton_wallet_code (публичный — в Jetton Master)
  - owner (адрес Alice)
  - master (адрес Jetton Master)

→ Мы можем вычислить адрес Alice's Jetton Wallet
  БЕЗ on-chain запроса!
Deterministic Address: вычисление вместо lookup
Ethereum: Lookup
TON: Compute

Практика: вычисление Jetton Wallet Address

// Off-chain (TypeScript, @ton/core)
import { Address, Cell, beginCell, contractAddress } from '@ton/core';

function getJettonWalletAddress(
  ownerAddress: Address,
  masterAddress: Address,
  walletCode: Cell
): Address {
  // Начальные данные для wallet контракта
  const data = beginCell()
    .storeCoins(0)              // initial balance = 0
    .storeAddress(ownerAddress)  // owner
    .storeAddress(masterAddress) // jetton master
    .storeRef(walletCode)       // wallet code (for verification)
    .endCell();

  // StateInit = code + data
  const stateInit = { code: walletCode, data };

  // Address = hash(workchain + state_init)
  return contractAddress(0, stateInit);
}

Свойства deterministic addresses

  1. Предсказуемость: адрес известен до deployment
  2. Уникальность: одинаковый code + data → одинаковый адрес (всегда)
  3. Immutability: адрес не может измениться после deployment
  4. Verifiability: любой может проверить hash(state_init) == actual_address

Contract Discovery без Registry

Паттерн: Get-method discovery

Master Contract предоставляет get-method для вычисления child address:

// Jetton Master get-method (off-chain call, бесплатно)
get_wallet_address(owner_address: Slice): Slice {
  return calculate_wallet_address(owner_address);
}

dApp workflow:

  1. Вызвать master.get_wallet_address(alice) → получить wallet_address
  2. Вызвать wallet.get_wallet_data() → получить balance

Оба вызова бесплатны (get-methods, off-chain).

Security: Preventing Fake Contracts

Атака: Impersonation

Злоумышленник деплоит контракт с адресом, похожим на легитимный wallet, и отправляет internal_transfer в Master.

Защита: Address Verification

Verification в Master:
1. Получить internal_transfer от sender
2. Вычислить expected_address = calc_wallet(claimed_owner)
3. sender == expected_address? 
   → Да: легитимный wallet, принять
   → Нет: подделка, ОТКЛОНИТЬ

Эта защита работает потому что:

  • Злоумышленник не может создать контракт с нужным адресом (hash collision невозможен)
  • Адрес = hash(code + data), злоумышленник не может подделать code или data
TIP

Pattern: Trustless Cross-Contract Verification

Этот паттерн применим везде: DEX pool проверяет что LP wallet легитимный, Lending market проверяет что position contract легитимный. Нет whitelist-ов, нет admin. Математика обеспечивает trust.

Design Guidelines

GuidelineОписание
Provide get-methodsMaster всегда должен иметь get_child_address(params)
Verify sendersВычислять expected address и сравнивать с actual sender
Include code in init_dataChild хранит wallet_code ref для self-verification
Predictable init_dataВсе поля init_data должны быть deterministic
Проверка знанийKnowledge check
ОтветAnswer

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 2. dApp хочет показать баланс Jetton Alice. Как найти адрес Alice's Jetton Wallet наиболее эффективно?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5