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







