BDS
smart-contracts, security-audits, ethereum-solidity

Обновление смарт-контрактов через прокси-шаблоны: полное руководство

23 февраля 2026 г.
12 мин
c
Архитектура прокси-шаблона, показывающая взаимодействие между прокси-контрактом, контрактом реализации и пользовательскими интерфейсами

Введение

Смарт-контракты запрограммированы так, чтобы быть постоянными и неизменяемыми после их развертывания в сети блокчейн. Эта неизменность является источником безопасности и доверия, но также создает проблемы, когда разработчикам нужно исправить ошибки или добавить новые функции.

Когда нужны изменения, разработчики должны выпускать совершенно новый контракт с другим адресом. Хотя такая постоянность отлично подходит для безопасности, она может быть ограничивающей в ситуациях, когда что-то идет не так или нужно что-то улучшить.

История показывает, что проблемы в смарт-контрактах могут привести к серьезным финансовым потерям. Один из примеров — крупный инцидент, когда из-за уязвимости, которую можно было использовать, были потеряны миллионы долларов.

Эти случаи показывают, как важно уметь решать проблемы с безопасностью и ошибки после запуска. Возможность обновлять контракты позволяет исправлять проблемы, не теряя текущее состояние и пользовательский опыт, что является ключевым моментом в обновляемости смарт-контрактов.

Эта функция может быть важной, чтобы избежать серьезных потерь и сохранить целостность системы.

Есть много способов реализовать обновляемые смарт-контракты, например, с помощью прокси-шаблонов и методов разделения данных. В этой статье мы поговорим о том, как сделать обновляемость с помощью прокси-шаблонов, которые часто используют в разработке блокчейнов.

Понимание шаблона прокси

Шаблон прокси — это структурный шаблон проектирования, где один контракт реализует интерфейс для другого контракта. Эта архитектура состоит из двух основных частей: контракта прокси и контракта реализации.

Вместо того, чтобы пользователь напрямую общался с контрактом реализации, он будет общаться с прокси-контрактом, который затем будет передавать запросы соответствующим образом.

В этой настройке и прокси-контракт, и контракт реализации не меняются после развертывания. Но возможность обновления достигается за счет того, что прокси может со временем ссылаться на разные контракты реализации.

Это значит, что пользователи могут продолжать использовать тот же адрес и интерфейс, пока обновляется функциональность базовой системы. С точки зрения пользователя, приложение продолжает работать отлично, даже если логика бэкэнда меняется.

Контракт-прокси отвечает за взаимодействие с пользователями и хранение всех данных. Он держит адрес контракта реализации в специальном месте хранения.

Когда пользователи вызывают функции в контракте-прокси, запускается резервная функция. Следующая функция использует механизм delegatecall ethereum для вызова кода из контракта реализации, но любые изменения состояния сохраняются в хранилище контракта-прокси.

Основные реализации шаблонов прокси

Шаблон прозрачного прокси

Шаблон «прозрачный прокси» помещает функцию обновления в сам контракт прокси. У прокси есть метод upgradeTo, который используется для обновления адреса, указывающего на контракт реализации.

Это может создать проблему: если и в прокси, и в контракте реализации есть метод upgradeTo, то не совсем понятно, какой из них нужно вызвать, когда пользователь запускает эту функцию.

Чтобы разобраться с этой неясностью, придумали решение, где выбор того, кому делегировать, зависит от того, кто вызывает контракт.

Если вызывающий является администратором прокси, вызовы обрабатываются самим контрактом прокси. В противном случае вызовы делегируются контракту реализации. Такой подход гарантирует, что функции выполняются четко и что нет путаницы между административными и обычными операциями пользователей.

Универсальный стандарт обновляемого прокси

Универсальный стандарт обновляемого прокси подходит по-другому, помещая функцию обновления в контракт реализации, а не в прокси. Прокси делегирует все вызовы контракту реализации, который имеет метод upgradeTo для указания на более новые версии.

Этот шаблон дает разработчикам больше контроля над процессом обновления. Если разработчик решит больше не включать метод upgradeTo в будущую версию, контракт станет неизменяемым и больше не сможет быть обновлен.

Это может быть полезно, когда контракт хорошо протестирован и команда разработчиков хочет зафиксировать его в окончательном виде.

Поскольку логика обновления есть в контракте реализации, нет нужды в резервной функции прокси, чтобы проверять, является ли вызывающий администратором, прежде чем делегировать вызовы.

Это делает паттерн более эффективным, чем паттерн прозрачного прокси. Также устраняется потенциальный конфликт имен, поскольку метод upgradeTo существует только в контракте реализации.

Шаблон прокси-маяка

Шаблон Beacon Proxy представляет архитектуру из трех частей: контракт прокси, контракт маяка и контракт реализации. Вместо того, чтобы сохранять адрес реализации, прокси сохраняет адрес контракта маяка.

Контракт маяка, в свою очередь, содержит адрес контракта реализации.

Когда пользователь вызывает прокси, сначала он получает адрес контракта маяка, а затем вызывает маяк, чтобы получить адрес контракта реализации. В конце концов, он оставляет вызов контракта реализации.

Этот дополнительный уровень косвенности нужен для очень конкретной цели.

Этот паттерн особенно полезен, когда несколько прокси-контрактов должны использовать одну и ту же реализацию. В более простых паттернах для обновления реализации нужно было бы обновлять адрес в каждом прокси-контракте по отдельности. С паттерном beacon нужно обновить только контракт beacon, и все связанные с ним прокси автоматически укажут на новую реализацию.

Основные реализации шаблонов прокси

Шаблон «алмазного прокси»

Шаблон Diamond Proxy Pattern решает проблему ограничения размера смарт-контрактов, которые обычно ограничены примерно 24 килобайт. Этот шаблон разделяет функциональность на несколько меньших контрактов, известных как фасеты.

Прокси-контракт сохраняет связь между селекторами функций и адресами аспектов, которые содержат эти функции.

Когда функция вызывается на прокси, она использует селектор функций, чтобы найти фасет, который содержит эту функцию, и делегирует вызов функции соответствующему фасету.

Обновления делаются путем изменения адресов фасетов в прокси. Этот подход позволяет добиться гораздо большей общей функциональности за счет распределения функциональности по нескольким контрактам, при этом каждый фасет остается в пределах ограничения по размеру.

Сравнение подходов к прокси-шаблонам

Каждый шаблон прокси имеет свои особенности, которые делают его подходящим для разных ситуаций. Все четыре шаблона нуждаются в контракте прокси и используют делегирование для перенаправления вызовов в контракты реализации.

Шаблон «Прозрачный прокси» помещает функции обновления в контракт прокси, а UUPS — в контракт реализации. Шаблон «Маяк» помещает функции обновления в свой собственный контракт маяка, а шаблон «Бриллиант» обычно помещает их в контракты реализации, но это не строго оговорено.

Что касается неизменности, то паттерны UUPS и Diamond могут сделать контракты постоянно неизменными, убрав функцию обновления из будущих версий. Паттерны Transparent и Beacon не дают такой гибкости.

Когда речь идет о нескольких прокси, паттерн Beacon имеет явное преимущество. С паттернами Transparent, UUPS и Diamond каждый прокси нужно менять по отдельности при внедрении новой реализации.

С шаблоном Beacon нужно обновить только контракт маяка, и все прокси автоматически начнут использовать новую реализацию.

Эффективность использования ресурсов у каждого шаблона своя. Шаблон Transparent требует, чтобы ты перед каждой делегацией проверял, является ли вызывающий администратором, поэтому он более затратен.

UUPS работает лучше, потому что не требует этой проверки. Все шаблоны, кроме Diamond, требуют дополнительных затрат газа на дополнительные операции поиска.

Все шаблоны, кроме Diamond, ограничены 24 килобайт на контракт. Шаблон Diamond позволяет каждому аспекту быть размером до 24 килобайт, что дает возможность иметь гораздо большую общую функциональность по нескольким аспектам.

Освойте безопасность смарт-контрактов

Изучите продвинутые методы создания безопасных обновляемых контрактов с помощью наших курсов под руководством экспертов.

Важные моменты и риски

Проблемы с конфликтами хранения

При использовании прокси-шаблонов есть риск конфликтов в хранилище. Переменные контракта хранятся в определенных ячейках хранилища, и если переменные прокси-контракта и переменные контракта реализации хранятся в одних и тех же ячейках, они будут мешать друг другу.

Кроме того, если порядок переменных в контракте реализации меняется от одной версии к другой, слоты хранения могут быть переназначены, что приведет к повреждению данных.

Неинициализированные контракты реализации

Контракты реализации должны инициализироваться ровно один раз через функцию инициализации, которая похожа на конструктор в традиционных контрактах.

Разработчики также забывают инициализировать реализацию или не включают защиту, чтобы функция инициализации не вызывалась больше одного раза.

Когда это происходит, злоумышленники могут сами вызвать функцию инициализации и, возможно, взять под контроль контракт или манипулировать его состоянием.

Реальные инциденты в сфере безопасности

Программа по поиску ошибок нашла серьезную уязвимость в контрактах прокси хранилища, где контракты реализации были неправильно инициализированы. Эта уязвимость могла быть использована злоумышленником для уничтожения контракта реализации, что сделало бы связанные с ним контракты прокси бесполезными. В другом случае в июле смарт-контракты были взломаны из-за уязвимости в коде инициализации, в котором функция инициализации могла вызываться несколько раз.

Другие способы обновления

Шаблон разделения данных

Альтернативой прокси-шаблонам является подход к разделению данных. Этот подход основан на использовании отдельных контрактов для хранения и логики. Логический контракт взаимодействует с контрактом хранения для чтения или обновления данных.

Хотя логический контракт можно заменить новыми версиями, контракт хранения фиксирован и не подлежит изменению. Это предлагает другую модель обновляемости, которая может быть уместна в некоторых случаях.

Уровни проверки

Ни один из обычно используемых шаблонов прокси не имеет механизмов для проверки действительности нового контракта реализации перед обновлением.

Новые версии обязательно должны включать всю нужную бизнес-логику, резервные функции и другие важные компоненты.

Это можно сделать, добавив слой проверки, который будет рядом со слоем прокси, слоем бизнес-логики и слоем хранения. Этот дополнительный слой гарантирует, что обновления будут соответствовать некоторым критериям, прежде чем их разрешат.

Лучшие практики для обновляемых контрактов

Разработчики, которые создают обновляемые контракты, должны следовать некоторым ключевым рекомендациям, чтобы обеспечить безопасность и надежность:

  • Вместо этого, полагайтесь на проверенные реализации из проверенных библиотек, которые были тщательно проверены и проаудитированы
  • Всегда проверяйте, чтобы контракты реализации были правильно инициализированы и чтобы функции инициализации можно было вызвать только один раз
  • Никогда не инициализируйте переменные состояния при их объявлении или в конструкторе, используйте функцию инициализации для настройки всего состояния
  • Не меняйте порядок или типы переменных состояния, когда делаете новые версии контрактов реализации
  • Если нужны новые переменные, то их нужно добавлять после всех уже существующих
  • Для реализации алгоритма Diamond используйте специальные методы хранения, которые подходят для этого алгоритма
  • Метод UUPS лучше, чем Transparent Proxy Pattern, если это возможно, потому что он требует меньше газа для обычных операций
  • Убедитесь, что учетная запись администратора прокси-сервера хорошо защищена, потому что она управляет процессом обновления и является важным элементом безопасности
  • И, наконец, перед развертыванием попросите опытных специалистов по безопасности смарт-контрактов проверить все контракты.

Заключительные мысли

Шаблоны прокси — это крутой способ обновлять смарт-контракты, не меняя адрес и состояние. Контракт прокси использует delegateCall, чтобы передать выполнение контрактам реализации, так что можно менять логику, не трогая пользовательский интерфейс.

Но если обновляемые контракты не реализованы как надо, они могут стать причиной серьезных проблем с безопасностью.

Разработчики должны внимательно взвешивать плюсы и минусы разных типов прокси-шаблонов, следовать лучшим практикам и проводить надлежащие проверки безопасности, чтобы создавать надежные и безопасные смарт-контракты, которые можно обновлять.

Сравнение шаблонов прокси

Когда сравниваешь, какой шаблон прокси использовать, есть несколько вещей, которые стоит учитывать:

Сравнение шаблонов прокси

ОсобенностьПрозрачностьUUPSBeaconБриллиант
Место обновленияПрокси-контрактДоговор о внедренииКонтракт BeaconКонтракты на внедрение
Постоянная неизменностьНетДаНетДа
Несколько проксиИндивидуальные обновленияИндивидуальные обновленияОбновление одного маякаИндивидуальные обновления
Эффективность использования газаБольше затрат (проверка администратором)Меньше затратСредний (дополнительный поиск)Средний (поиск по фасетам)
Ограничение по размеру контракта24 КБ24 КБ24 КБ24 КБ на каждый аспект
Сложность реализацииСреднийСреднийСреднийСредний

Что нужно учитывать при выборе шаблона

Что важно при выборе шаблона:

  • Все шаблоны должны иметь прокси-контракт и использовать делегирование для передачи вызовов
  • Шаблон прозрачного прокси используется для хранения функций обновления в самом контракте прокси
  • UUPS добавляет функции обновления в контракт реализации
  • Шаблон Beacon использует отдельный контракт beacon для обновлений
  • В модели Diamond функции обновления обычно помещаются в контракты реализации, но спецификация не требует этого
  • Только UUPS и Diamond позволяют сделать контракты полностью неизменяемыми, убрав функцию обновления из будущих версий
  • Шаблон Beacon идеально подходит, если вам нужно обновить сразу несколько прокси, потому что обновлять нужно только маяк, а не каждый прокси
  • Максимальный размер контракта — 24 килобайт для шаблонов Transparent, UUPS и Beacon
  • Шаблон Diamond позволяет каждому аспекту быть размером до 24 килобайт, так что можно поддерживать гораздо больше функций
  • Все шаблоны имеют среднюю сложность реализации, и для шаблонов Transparent, UUPS и Beacon есть хорошо налаженные библиотеки

FAQ

#proxy patterns
#smart contract upgradeability
#blockchain security
Похожие материалы

Похожие статьи

Откройте для себя больше идей и решений в наших избранных статьях

BDS

Пионеры в области блокчейн-технологий с инновационными решениями, которые расширяют возможности бизнеса и частных лиц по всему миру.

+1 929 560 3730 (США)
+44 2045 771515 (Великобритания)
+372 603 92 65 (Эстония)
Округ Харью, Таллинн, Ласнамяэ, ул. Катусепапи 6-502, 11412, Эстония

Будьте в курсе

Получайте последние новости блокчейна прямо на вашу почту.