Паттерн Proxy/Upgradable на TON

Спроектируешь proxy+implementation: стабильный адрес для клиентов и смена логики через admin.

Proxy / Upgradable

Прямой setCode меняет код того же адреса. Паттерн proxy разделяет роли: proxy держит адрес и storage (или маршрутизацию), implementation — логику. Клиенты всегда пишут в proxy; admin меняет ссылку на implementation или код proxy по жёстким правилам.

На TON нет «delegatecall как в EVM». Proxy обычно пересылает сообщения в implementation или сам хранит state и меняет только code.


Proxy с переключаемой логикой

tact (fallback highlight)
// @tact-lang/compiler 1.6.13

message SetImplementation {
    next: Address;
}

message Exec {
    payload: Cell;
}

contract LogicV1(
    proxy: Address,
    acc: Int as uint64,
) {
    receive() { cashback(sender()) }

    receive(msg: Exec) {
        require(sender() == self.proxy, "only proxy");
        self.acc += 1;
        // бизнес-логика v1
        cashback(sender());
    }

    get fun acc(): Int { return self.acc }
}

contract Proxy(
    owner: Address,
    implementation: Address,
) {
    receive() { cashback(sender()) }

    receive(msg: SetImplementation) {
        require(sender() == self.owner, "not owner");
        self.implementation = msg.next;
        cashback(sender());
    }

    receive(msg: Exec) {
        message(MessageParameters{
            to: self.implementation,
            value: 0,
            mode: SendRemainingValue,
            bounce: true,
            body: Exec{ payload: msg.payload }.toCell(),
        });
    }

    get fun implementation(): Address {
        return self.implementation;
    }
}

Как это работает

  • Клиент знает только адрес Proxy — ABI/обёртки стабильны снаружи.
  • SetImplementation переключает целевой контракт; state в примере живёт в LogicV1 (при смене реализации миграция отдельная задача).
  • Альтернатива: state в Proxy, а implementation — библиотека/модуль, либо апгрейд через setCode на самом Proxy (проще, но сильнее связывает storage и код).
  • require(sender() == self.proxy) на LogicV1 отсекает прямые вызовы в обход proxy.
  • Для прод-апгрейда добавь timelock/multisig на owner (см. статьи про timeout и set_code).

Частые ошибки

Сменил implementation, забыв миграцию storage → новый код смотрит пустой/чужой state.

Implementation принимает сообщения от кого угодно → обход proxy и рассинхрон инвариантов.

Proxy глотает bounce без политики → клиент думает, что Exec прошёл; обрабатывай bounce или делай синхронный ack-протокол.


Что дальше

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