Составление: План перевода; Источник: soliditylang.org
Выпущена последняя версия компилятора Solidity v0.8.22. Компилятор версии 0.8.22 включает в себя ряд улучшений языка и компилятора, таких как определения событий на уровне файлов, инкрементная оптимизация непроверенных циклов, поддержка импорта JSON сборки EVM и многое другое.
ВАЖНО!
В этом выпуске прекращена поддержка EVM ниже Constantinople (Constantinople), которые становится все труднее поддерживать. Эти архаичные версии уже давно устарели в основной сети Ethereum и тестовой сети, и мы подозреваем, что они больше не актуальны и для других сетей. Сложные пути кода и решения замедляют разработку функций и тестирование новых версий, поэтому мы планируем прекратить их поддержку в будущих выпусках компилятора. Если вы рассчитываете на поддержку этих версий EVM, свяжитесь с нами[6] 。
Основные моменты новых функций
неотмеченное приращение цикла
Использование непроверенной арифметики при увеличении счетчика контура для оптимизации газа[7] Общепринятая практика. Проиллюстрируем это на следующем примере цикла и счетчика i:
for (uint i = 0; i < array.length; ++i) {
acc += массив[i] ; i не изменяется телом цикла
}
Во многих случаях (см. точные условия ниже) операция сравнения гарантирует, что i никогда не достигнет максимального значения своего типа, поэтому можно с уверенностью предположить, что цикл остановится до того, как будет достигнуто максимальное значение. В этом случае проверка безопасности счетчика была бы излишней и пустой тратой газа. Это побуждает пользователя использовать длинный шаблон unchecked, который инкрементально оборачивает счетчик в непроверенный арифметический блок внутри цикла, минуя проверку:
for (uint i = 0; i < array.length;) {
acc += массив[i] ;
unchecked { i++; } // i увеличивается без проверок переполнения -- используется меньше газа
}
В Solidity 0.8.22 введена оптимизация проверки переполнения, которая автоматически генерирует непроверенное арифметическое приращение для счетчика цикла. Эта новая оптимизация избавляет от необходимости использовать длинный непроверенный дельта-шаблон в телах циклов, как в предыдущем примере.
В отличие от этого, новые оптимизации позволяют пользователям вернуться к сырому, более читаемому коду без ущерба для эффективности использования газа.
Точные условия для новой оптимизированной проверки предотвращения разливов следующие:
Условия цикла имеют форму i < ... где i — локальная переменная (далее называемая «счетчиком цикла»).
Это сравнение должно выполняться для того же типа, что и счетчик цикла, т.е. тип справа должен быть неявно преобразован в тип счетчика цикла, чтобы счетчик цикла не был неявно расширен перед сравнением.
Счетчик цикла должен быть локальной переменной встроенного целочисленного типа.
Выражение цикла должно быть префиксом или суффиксом приращения для счетчика цикла, i++ или ++i.
Счетчик циклов не может быть изменен в условиях цикла или в теле цикла.
Чтобы прояснить второе условие, рассмотрим следующий фрагмент кода:
for (uint8 i = 0; in < UINT16(1000); ++I) {
Тело петли
}
В этом случае i преобразуется в uint16 перед сравнением, и условие никогда не бывает ложным, поэтому инкрементная проверка переполнения не может быть удалена.
Кроме того, обратите внимание, что < является единственным оператором сравнения, который запускает оптимизацию. Оператор <= и другие операторы намеренно исключены. Кроме того, оператор должен быть встроенным - пользовательский < не подходит.
Оптимизация проста и всегда полезна, поэтому она будет включена, даже если остальная часть оптимизатора отключена с помощью общей настройки settings.optimizer.enabled. Вы можете явно отключить его, задав settings.optimizer.details.simpleCounterForLoopUncheckedIncrement значение false в стандартных входных данных JSON. Его нельзя отключить с помощью интерфейса командной строки.
Настройте оптимизатор Yul на регенерацию нулевых литералов
Новая версия основана на поддержке кодов операций PUSH0, представленной в версии 0.8.20, путем добавления Rematerialiser[8] [9] Шаг оптимизации расширен для того, чтобы всегда восстанавливать нулевой литерал вместо того, чтобы хранить его в качестве ссылки на переменную, что позволяет использовать PUSH0 вместо DUP для снижения затрат на газ. Чтобы убедиться, что это сделано эффективно, добавлены Rematerialiser и UnusedPruner Шаги добавляются в последовательность очистки оптимизатора Yul по умолчанию.
Добавлена поддержка импорта сборки EVM JSON (экспериментально)
В этом новом выпуске добавлена экспериментальная поддержка импорта сборок EVM, что открывает возможность для внешних инструментов выполнять супероптимизацию перед генерацией байт-кода. Основной целью этой функции является определение формата сериализации для низкоуровневых сборок EVM, чтобы сборки, созданные компилятором, можно было экспортировать, изменять и повторно импортировать, тем самым возобновляя нормальный процесс компиляции.
Важно: Это экспериментальная функция, которая в настоящее время недоступна в рабочей среде. Мы предлагаем эту функцию в этом выпуске, чтобы вы могли опробовать ее и оставить отзыв.
Позволяет определять события на уровне файла
Solidity 0.8.22 позволяет определять события на уровне файла. Определения событий теперь можно размещать за пределами контракта. Это дает еще один вариант организации кода без необходимости искусственно оборачивать события в библиотеку.
Кроме того, в этом выпуске исправлена ошибка, которая вызывала ошибку при генерации NatSpec при генерации события, определенного во внешнем контракте или интерфейсе для кода. В предыдущем релизе (0.8.21) компилятор Solidity добавил поддержку ограниченного доступа к событиям, определенным в контрактах и интерфейсах, которые не наследуются от текущего контракта, но ошибка не позволяла полноценно использовать эту функцию.
Благодаря этому исправлению ошибки и разрешению определений событий на уровне файла, последняя версия Solidity позволяет пользователям компилировать следующие примеры без каких-либо ошибок:
интерфейс I {
событие ForeignEvent();
}
контракт C {
событие ForeignEvent();
}
событие E();
контракт D {
function f() public {
Генерация стороннего события вызывала внутреннюю ошибку в версии 0.8.21
emit I.ForeignEvent();
emit C.ForeignEvent();
Создание события на уровне файла. Новая функция.
выдаем E();
}
}
Полный список изменений
Особенности языка
Позволяет определять события на уровне файла.
Возможности компилятора
Генератор кода: Удалены избыточные проверки переполнения для некоторых циклов for, когда переменная count не переполняется.
Интерфейс командной строки: Добавлена опция --no-import-callback, чтобы предотвратить загрузку компилятором исходных файлов, которые явно не указаны в CLI или стандартных входных данных JSON.
Интерфейс командной строки: Добавлена экспериментальная опция --import-asm-json для импорта сборок EVM в формате, используемом --asm-json.
Интерфейс командной строки: используйте соответствующую серьезность и цвет для сообщений об ошибках, созданных за пределами скомпилированного конвейера.
EVM: Устарела поддержка версий EVM "homestead", "tangerineWhistle", "spuriousDragon" и "byzantium".
Парсер: Удален экспериментальный режим восстановления ошибок (--error-recovery/settings.parserErrorRecovery).
SMTChecker: Поддерживает пользовательские операторы.
Yul Optimizer: Если поддерживается PUSH0, предпочитает использовать нулевые литералы вместо хранения нулевых значений в переменных.
Yul Optimizer: Запускает шаги Rematerializer и UnusedPruner в конце последовательности очистки по умолчанию.
Исправление ошибок
Генератор кода: Исправлена проблема, из-за которой вывод через генератор кодов via-IR зависел от файлов, найденных в обратных вызовах импорта. В некоторых случаях различные назначения идентификаторов AST могут изменять порядок функций во внутреннем планировании, что приводит к внешне различным, но семантически эквивалентным байт-кодам.
NatSpec: Исправлена внутренняя ошибка при запросе пользовательской документации или документации по разработке для контракта, который выдавал событие, определенное во внешнем контракте или интерфейсе.
SMTChecker: Исправлена ошибка кодирования, из-за которой цикл расширялся после завершения.
SMTChecker: Исправлены несоответствия в проверках постоянных условий при раскручивании цикла while или for перед проверкой условия.
Yul Optimizer: Исправлена проблема, из-за которой имена переменных Yul, сгенерированные компилятором во время CSE, влияли на решения о замене, что приводило к другому (но эквивалентному) байт-коду в некоторых случаях.
Посмотреть Оригинал
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
Выпущена новая версия Solidity, самого популярного языка разработки смарт-контрактов Ethereum
Составление: План перевода; Источник: soliditylang.org
Выпущена последняя версия компилятора Solidity v0.8.22. Компилятор версии 0.8.22 включает в себя ряд улучшений языка и компилятора, таких как определения событий на уровне файлов, инкрементная оптимизация непроверенных циклов, поддержка импорта JSON сборки EVM и многое другое.
ВАЖНО!
В этом выпуске прекращена поддержка EVM ниже Constantinople (Constantinople), которые становится все труднее поддерживать. Эти архаичные версии уже давно устарели в основной сети Ethereum и тестовой сети, и мы подозреваем, что они больше не актуальны и для других сетей. Сложные пути кода и решения замедляют разработку функций и тестирование новых версий, поэтому мы планируем прекратить их поддержку в будущих выпусках компилятора. Если вы рассчитываете на поддержку этих версий EVM, свяжитесь с нами[6] 。
Основные моменты новых функций
неотмеченное приращение цикла
Использование непроверенной арифметики при увеличении счетчика контура для оптимизации газа[7] Общепринятая практика. Проиллюстрируем это на следующем примере цикла и счетчика i:
for (uint i = 0; i < array.length; ++i) {
acc += массив[i] ; i не изменяется телом цикла
}
Во многих случаях (см. точные условия ниже) операция сравнения гарантирует, что i никогда не достигнет максимального значения своего типа, поэтому можно с уверенностью предположить, что цикл остановится до того, как будет достигнуто максимальное значение. В этом случае проверка безопасности счетчика была бы излишней и пустой тратой газа. Это побуждает пользователя использовать длинный шаблон unchecked, который инкрементально оборачивает счетчик в непроверенный арифметический блок внутри цикла, минуя проверку:
for (uint i = 0; i < array.length;) {
acc += массив[i] ;
unchecked { i++; } // i увеличивается без проверок переполнения -- используется меньше газа
}
В Solidity 0.8.22 введена оптимизация проверки переполнения, которая автоматически генерирует непроверенное арифметическое приращение для счетчика цикла. Эта новая оптимизация избавляет от необходимости использовать длинный непроверенный дельта-шаблон в телах циклов, как в предыдущем примере.
В отличие от этого, новые оптимизации позволяют пользователям вернуться к сырому, более читаемому коду без ущерба для эффективности использования газа.
Точные условия для новой оптимизированной проверки предотвращения разливов следующие:
Чтобы прояснить второе условие, рассмотрим следующий фрагмент кода:
for (uint8 i = 0; in < UINT16(1000); ++I) {
Тело петли
}
В этом случае i преобразуется в uint16 перед сравнением, и условие никогда не бывает ложным, поэтому инкрементная проверка переполнения не может быть удалена.
Кроме того, обратите внимание, что < является единственным оператором сравнения, который запускает оптимизацию. Оператор <= и другие операторы намеренно исключены. Кроме того, оператор должен быть встроенным - пользовательский < не подходит.
Оптимизация проста и всегда полезна, поэтому она будет включена, даже если остальная часть оптимизатора отключена с помощью общей настройки settings.optimizer.enabled. Вы можете явно отключить его, задав settings.optimizer.details.simpleCounterForLoopUncheckedIncrement значение false в стандартных входных данных JSON. Его нельзя отключить с помощью интерфейса командной строки.
Настройте оптимизатор Yul на регенерацию нулевых литералов
Новая версия основана на поддержке кодов операций PUSH0, представленной в версии 0.8.20, путем добавления Rematerialiser[8] [9] Шаг оптимизации расширен для того, чтобы всегда восстанавливать нулевой литерал вместо того, чтобы хранить его в качестве ссылки на переменную, что позволяет использовать PUSH0 вместо DUP для снижения затрат на газ. Чтобы убедиться, что это сделано эффективно, добавлены Rematerialiser и UnusedPruner Шаги добавляются в последовательность очистки оптимизатора Yul по умолчанию.
Добавлена поддержка импорта сборки EVM JSON (экспериментально)
В этом новом выпуске добавлена экспериментальная поддержка импорта сборок EVM, что открывает возможность для внешних инструментов выполнять супероптимизацию перед генерацией байт-кода. Основной целью этой функции является определение формата сериализации для низкоуровневых сборок EVM, чтобы сборки, созданные компилятором, можно было экспортировать, изменять и повторно импортировать, тем самым возобновляя нормальный процесс компиляции.
Важно: Это экспериментальная функция, которая в настоящее время недоступна в рабочей среде. Мы предлагаем эту функцию в этом выпуске, чтобы вы могли опробовать ее и оставить отзыв.
Позволяет определять события на уровне файла
Solidity 0.8.22 позволяет определять события на уровне файла. Определения событий теперь можно размещать за пределами контракта. Это дает еще один вариант организации кода без необходимости искусственно оборачивать события в библиотеку.
Кроме того, в этом выпуске исправлена ошибка, которая вызывала ошибку при генерации NatSpec при генерации события, определенного во внешнем контракте или интерфейсе для кода. В предыдущем релизе (0.8.21) компилятор Solidity добавил поддержку ограниченного доступа к событиям, определенным в контрактах и интерфейсах, которые не наследуются от текущего контракта, но ошибка не позволяла полноценно использовать эту функцию.
Благодаря этому исправлению ошибки и разрешению определений событий на уровне файла, последняя версия Solidity позволяет пользователям компилировать следующие примеры без каких-либо ошибок:
интерфейс I {
событие ForeignEvent();
}
контракт C {
событие ForeignEvent();
}
событие E();
контракт D {
function f() public {
Генерация стороннего события вызывала внутреннюю ошибку в версии 0.8.21
emit I.ForeignEvent();
emit C.ForeignEvent();
Создание события на уровне файла. Новая функция.
выдаем E();
}
}
Полный список изменений
Особенности языка
Возможности компилятора
Исправление ошибок