Минимальный прокси: почему деплой контрактов съедает бюджет
Каждый новый экземпляр контракта в EVM — это повторная запись всего байткода в хранилище сети. Стоимость деплоя контракта складывается не из логики, а из объёма: сеть берёт плату за каждые 32 байта кода, и при развёртывании фабрикой десятков однотипных экземпляров вы платите за один и тот же код многократно. Минимальный прокси убирает именно это дублирование: вместо копии логики на цепочку кладётся короткий контракт-указатель, который делегирует все вызовы единственному уже развёрнутому экземпляру реализации.
Механика простая. Прокси хранит адрес реализации и через DELEGATECALL выполняет её код в своём контексте — со своим хранилищем, своим балансом и своим адресом. Байткод реализации деплоится один раз, а каждый новый экземпляр стоит ровно столько, сколько занимает сам прокси — десятки байт вместо килобайт. Газ при развёртывании падает на порядок, и это не разовая экономия: она масштабируется на каждую новую сущность, которую вы создаёте.
Вторая статья расходов — обновления. Без прокси любая правка логики означает повторный деплой байткода и миграцию состояния: старые экземпляры остаются на прежней версии, новые живут отдельно, а история разъезжается. С минимальным прокси вы меняете адрес реализации — все экземпляры разом начинают работать по новой логике, состояние остаётся на месте. Повторный деплой байткода превращается в одну транзакцию обновления указателя.
Цена решения тоже известна, и её нужно закладывать заранее. Прокси не может иметь конструктор — начальные параметры передаются отдельной функцией инициализации, которую обязательно защищают от повторного вызова. Хранилище прокси и реализации живёт в одном слоте, поэтому порядок переменных фиксируется с первого дня: перестановка полей при обновлении ломает состояние. Читаемость кода в обозревателе сети падает — видно прокси, а логику приходится смотреть по адресу реализации.
Именно на этих границах чаще всего спотыкаются команды, которые внедряют паттерн без разбора. Дальше разбираем, как это закрывается: где минимальный прокси даёт максимальный выигрыш, а где дешевле оставить прямой деплой.
Как минимальный прокси снижает стоимость развёртывания
Минимальный прокси — это контракт-обёртка, который хранит адрес логики и делегирует ей все вызовы через DELEGATECALL. Байткод такого прокси укладывается в несколько десятков байт против тысяч у полноценного контракта, поэтому в блокчейн записывается лишь небольшая обёртка, а тяжёлая логика разворачивается один раз. При клонировании контракта каждый новый экземпляр стоит на порядок меньше газа, чем полная повторная публикация кода.
Что даёт сокращение байткода
Развёртывание — самая дорогая операция в сети: газ считается за каждый записанный байт. Шаблон прокси убирает из транзакции тело логики, оставляя только ссылку на неё. На потоке однотипных контрактов — токенов, хранилищ, экземпляров под каждого клиента — это переводит стоимость из «каждый раз заново» в «один раз плюс дешёвые копии».
Фабрика контрактов и единая логика
Фабрика контрактов разворачивает прокси по предсказуемому адресу и передаёт в конструктор параметры конкретного экземпляра. Логика при этом остаётся общей: обновление поведения делается в одном месте и подхватывается всеми клонами. Побочный эффект — предсказуемые адреса, которые удобно закладывать в интеграции заранее.
Измеримый эффект
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Полное развёртывание | Уникальная логика, единичный контракт | Максимальная стоимость транзакции, дублирование кода |
| Шаблон прокси (EIP-1167) | Много однотипных экземпляров | Логика общая, состояние — у каждого своё |
| Фабрика контрактов | Поток клонов с параметрами | Нужна аккуратная работа с адресами и правами |
На практике переход на минимальный прокси сокращает байткод экземпляра в десятки раз и снижает газ развёртывания на порядок — при потоке из сотен клонов разница в стоимости транзакции становится решающей. Подход стандартизирован в EIP-1167, поэтому совместим с большинством инструментов сборки и верификации.
Что если логику нужно обновить? Прокси хранит адрес реализации отдельно, поэтому смена логики не требует перевыпуска клонов — обновляется одна общая часть.
Внедрение минимального прокси: этапы инженерной работы
Внедрение минимального прокси начинается с аудита контрактов: смотрим, какие логические контракты переиспользуются между инстансами, где дублируется байткод и какие функции должны остаться неизменяемыми. По итогам фиксируем, что выносится в общую реализацию, а что остаётся в прокси, — от этого зависит и схема развёртывания, и объём хранилища под каждый инстанс.
Дальше выстраиваем процесс так, чтобы фабрика была предсказуемой, а обновление логики не ломало уже созданные инстансы.
- Аудит контрактов. Разбираем текущий код, выделяем общие библиотеки и функции, проверяем, где хранение привязано к адресу и не переносится в прокси без изменений.
- Проектирование схемы развёртывания. Определяем, как прокси ссылается на реализацию, как инициализируется состояние и как разделяются права на обновление логики и на управление инстансами.
- Настройка фабрики. Собираем фабрику, которая разворачивает прокси детерминированно, с проверкой адреса и защитой от повторной инициализации.
- Тестирование прокси. Прогоняем сценарии: создание инстанса, вызовы через делегирование, обновление реализации, откат и поведение при ошибках в логике.
- Проверка на тестовой сети. Разворачиваем фабрику и несколько инстансов, сверяем адреса, расход газа на создание и корректность состояния после вызовов.
- Передача решения. Отдаём настроенную фабрику, скрипты развёртывания, схему хранения и инструкцию по добавлению новых инстансов.
- Сопровождение после запуска. Помогаем с первым боевым развёртыванием и фиксируем порядок обновления логики без миграции уже созданных прокси.
Такой порядок убирает главный риск — когда прокси созданы, а логику обновить нельзя без перевыпуска всех инстансов. Аудит и тесты на ранних этапах показывают это до боевого запуска, а не после.
Чем минимальный прокси отличается от обычного прокси?
Минимальный прокси — это контракт, который не содержит логики приложения вообще. Всё, что в нём есть: инструкция делегирования вызовов и зашитый адрес реализации. Любой вызов, пришедший на адрес прокси, через DELEGATECALL уходит в контракт-реализацию, и код исполняется в контексте хранилища прокси. Сам прокси при этом не хранит ни переменных, ни состояния — только неизменяемый адрес, вкомпилированный в байткод. Именно поэтому его размер — десятки байт, а не килобайты.
Обычный обновляемый прокси устроен иначе. Он хранит адрес реализации в слоте хранилища, а значит — умеет его менять: добавить функцию upgradeTo, проверить права администратора, обновить переменную. За это приходится платить: логика обновления — это код, код занимает место в байткоде, а слот с адресом нужно защищать от коллизий с хранилищем реализации. Отсюда целые схемы вроде EIP-1967, где адрес реализации кладут в псевдослучайный слот, чтобы он не пересекался с переменными логики.
Разница в цене деплоя — прямое следствие разницы в размере. Минимальный прокси при развёртывании записывает в блокчейн только короткий байткод, поэтому стоит на порядок меньше, чем полноценный обновляемый прокси с логикой апгрейда. Когда вы поднимаете сотни или тысячи одинаковых экземпляров — например, по одному контракту на пользователя или на лот, — эта разница накапливается в разы по суммарным затратам на развёртывание.
Обратная сторона: минимальный прокси неизменяем. Адрес реализации зашит в байткод, и поменять его после деплоя нельзя — обновить логику у уже созданных экземпляров не выйдет. Обновляемый прокси такую возможность даёт, но добавляет поверх делегирования слой управления: кто имеет право на апгрейд, как защищены слоты, что происходит при ошибке в новой реализации. Это не «лучше» или «хуже» — это выбор между экономией на деплое и гибкостью обновления.
На практике выбор такой: если логика финальная и меняться не будет, а экземпляров много — минимальный прокси. Если контракт будет развиваться, а экземпляр один-два — обновляемый прокси, где накладные расходы на управление оправданы. Смешанный вариант тоже встречается: обновляемая реализация плюс минимальные прокси, указывающие на неё, — тогда логику можно обновить один раз для всех клонов.
Кейс: сокращение стоимости деплоя в 10 раз для сети маркетплейсов
Заказчик — сеть региональных маркетплейсов — выводил новый торговый контракт под каждый город и категорию. Каждый деплой тянул полный байткод с логикой лотов, ставок и расчётов: один и тот же код уезжал в сеть десятки раз, и за это приходилось платить газом заново. На десятом контракте стало видно узкое место: выпуск новой витрины занимал часы и упирался в стоимость записи кода в блокчейн.
Мы разобрали логику на два слоя. Общая часть — правила торгов, комиссии, роли — вынесена в один эталонный контракт-реализацию. Каждая новая витрина стала минимальным прокси: короткий контракт, который хранит адрес реализации и делегирует вызовы ей. Такой прокси укладывается в несколько десятков байт, поэтому в сеть пишется только ссылка, а не весь код.
Что изменилось в цифрах
| Метрика | До | После |
|---|---|---|
| Газ на деплой витрины | эталон | ~1/10 от эталона |
| Время выпуска новой витрины | часы | минуты |
| Правка логики во всех витринах | по каждому контракту | одна реализация |
Отдельно закрыли вопрос обновляемости: за прокси закреплён контроллер, который переключает адрес реализации. Правка правил торгов раскатывается на все витрины разом, без передеплоя и без миграции состояния — данные остаются на месте. Ограничение честно зафиксировали: прокси не хранит собственную логику, поэтому вся она обязана жить в реализации, а конструктор заменён на явный инициализатор.
Результат: сеть масштабируется до новых городов без роста расходов на газ пропорционально числу контрактов, а выпуск витрины перестал быть отдельной инженерной задачей. Подход опирается на EIP-1167 — стандарт минимального прокси, проверенный в бою на тысячах контрактов.
Сомнения и гарантии: совместимость, миграция, откат
Прокси-контракт — это отдельный слой адресации, и главный технический риск здесь не в экономии газа, а в том, что логика и хранилище живут раздельно. Minimal proxy (EIP-1167) делегирует вызовы в реализацию через delegatecall, поэтому состояние остаётся на адресе прокси, а код — на адресе логики. Отсюда два практических вопроса: что делать, если реализацию нужно обновить, и что произойдёт с уже накопленными данными пользователей.
Можно ли обновить логику, не потеряв состояние и адрес контракта?
Да, если архитектура заложена заранее. Адрес прокси неизменен — меняется только указатель на реализацию, а хранилище остаётся на месте. Критично другое: порядок и типы переменных в новом коде должны совпадать со старым, иначе данные «съедут». Поэтому мы фиксируем схему хранилища до первого деплоя и проверяем каждое обновление на тестовой сети с реальным слепком состояния.
Что если нужен откат? Откат делается возвратом указателя на предыдущую реализацию — при условии, что её адрес сохранён, а состояние не изменилось необратимо. Мы держим историю реализаций и описываем, какие операции откатываемы, а какие нет.
Как устроены доступы? Роли на обновление, паузу и вывод средств разведены и вынесены в отдельный контракт управления. Ключи — мультиподпись, а не один кошелёк.
Совместимо ли с текущим стеком? Minimal proxy — стандарт, его понимают все основные обозреватели блоков, кошельки и инструменты верификации. Ограничение одно: логика не должна использовать конструктор для инициализации — начальные значения задаются отдельным вызовом.
После работы заказчик получает на руки:
- исходники прокси и реализации с настройками компилятора;
- схему хранилища с правилами совместимости при обновлениях;
- контракт управления с матрицей ролей и порогами подписей;
- скрипты деплоя и обновления, воспроизводимые на тестовой сети;
- процедуру отката с перечнем обратимых операций;
- отчёт о проверках и результаты тестов на слепке реального состояния;
- документацию по адресам, ролям и порядку действий при инциденте.
Опишите вашу задачу — вернёмся с оценкой и планом: какие контракты уже в сети, как устроено хранилище и что планируется менять.







