как контракт стоит меньше газа в структурах?

У меня есть несколько вопросов.

  1. у нас есть типы int, когда uint8, uint16, uint32, etc.я прочитал это:

Обычно от использования этих подтипов нет никакой пользы, потому что Solidity резервирует 256 бит памяти независимо от размера uint. Например, использование uint8 вместо uint (uint256) не сэкономит вам газа.

Итак, если я наберу непосредственно в контракте переменную состояния, что-то вроде этого:

  • uint8 тест1;
  • uint32 тест2;
  • uint тест3;

uint8 testПочему везде, где я его использую, потребление газа не будет меньше, чем uint32 test2? Я спрашиваю, потому что с uint8 test1, я использую меньше места для хранения.

  1. Допустим, я использую структуру по-другому.
// way1
struct Person {
  uint8 test1;
  uint32 test2;
  uint8 test3;
}


// way2
struct Person {
  uint8 test1;
  uint8 test2;
  uint32 test3;
}

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

Ответы (1)

Это о том, как переменные упакованы вместе и о том, насколько умен компилятор (подсказка: не очень умен). Компилятор только пытается упаковать последующие переменные вместе, но он не может упаковать переменные, между которыми есть что-то еще.

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

Вы можете прочитать больше об упаковке переменных, например, здесь: https://fravoll.github.io/solidity-patterns/tight_variable_packing.html

Итак, если я не использую структуру, а просто использую uint8 test1; uint8 тест2; в качестве переменных состояния (глобальных) в контракте они (каждая из них) используют 32-байтовые слоты отдельно, хотя они могли бы использовать один и тот же слот, но все же нет, они используют отдельные и в случае uint8 (8 бит), 256-8 = 248 бит просто ничего не делают, верно? поэтому для переменных состояния мне не нужно ни о чем думать, и я могу просто набирать uint все время. если это структура, вот где я должен думать. соглашаться ?
Этот шаблон работает и для переменных состояния. Цитата из ссылки: «Как указано в разделе «Применимость», этот шаблон можно использовать для переменных состояния, внутри структур и для массивов статического размера»