February 15, 2022

Gas и memory types

Привет, друзья!

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

Введение

Всего EVM предлагает 4 вида памяти:

  • Storage (хранилище)
  • Memory (память)
    • Stack (привычный стэк)
    • Calldata (данные при вызове)

Storage

Самый дорогой вид памяти. Каждый контракт обладает собственной storage памятью (аналог жесткого диска в понимании). Здесь хранятся все глобальные переменные (state variables), состояние которых постоянно между вызовами функций. Таким образом, между всеми обращения к контракту - эти значения сохраняются. Представляет собой ассоциативный массив (словарь, map), с uint256 ключами и uint256 значениями.

Memory

Второй тип памяти. Намного дешевле, чем storage, очищается между внешними вызовами функций и используется для хранения временных данных: локальные переменные, адреса возврата из функции. Аналог для понимания - оперативная память. По внутреннему устройству - представляет из себя байт-массив. Сначала имеет нулевой размер, но может быть расширена 32-байтовыми порциями (256 бит).

Stack

Как было сказано в прошлых статьях, EVM - язык, основанный на стэке. Стэк используется для хранения локальных переменных и возвращаемых адресов из функции. Каждый элемент стека - 256 бит, максимальная глубина стэка - 1024 элемента. Однако, только верхние 16 элементов доступны для использования. Если стэк переполнить, то выполнение контракта прервется. Цена использования - практически аналогична Memory.

Длина "слова" (элемента стэка) в 256 бит выбрана не случайно - это очень удобно для использования криптографических функций (напр. Keccak-256, secp256k1).

Calldata

Это память только для чтения, которая не хранится постоянно. Используется лишь для хранения аргументов функции. В большинстве источников не упоминается вовсе. Заслуги calldata перекладываются на memory.

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

В Solidity можно явно указать используемый тип память (memory or storage), но не всегда можно это сделать. Когда это может обернуться ошибкой - предлагаем прочитать в замечательных статьях ниже. А мы прощаемся с Вами до завтра, чтобы суметь поискать что-то поучительно и интересное;)

Материалы:

  1. Статья о сравнении типов памяти и расчетах стоимости
  2. Еще хорошая статья о типах памяти
  3. Забавная ситуация, которая может произойти по недостатку теоретической базы
  4. Приличный список хороших советов по работе с памятью в Solidity
  5. Статья, послужившая основной идеей текущей заметки
  6. Прекрасная презентация с иллюстрациями принципов работы Ethereum
  7. Официальная документация Ethereum
  8. 8. Большая статья на русском языке от 2017г (в переводе) об Ethereum (можно найти ответы на вопросы, которые могут появиться при изучении презентации из п.1 или при прочтении данной статьи)