Что делает байт-код пустого контракта?

Когда я компилирую пустой контракт:

contract A {}

с

solc --optimize --optimize-runs 300000 --opcodes test.sol

Я получил:

PUSH1 0x60 PUSH1 0x40 MSTORE PUSH1 0x6 DUP1 PUSH1 0x10 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN PUSH1 0x60 PUSH1 0x40 MSTORE STOP

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

Вероятно

PUSH1 0x60 PUSH1 0x40 MSTORE

это шаблон для выделения 64 байта (0x40) в памяти. Если да, то почему нам нужно выделять его вручную?

В желтой бумаге есть несколько строк о разделении «кода» и «данных». Я вижу это при запуске solcс --asm-json. Но как эти две части на самом деле взаимодействуют?

Я чувствую, что пропустил очень важную статью или руководство, где все прояснено. Где я могу получить это?

Обобщить:

  1. Что делает байт-код пустого контракта? Если это возможно, мне нужно объяснение для каждого опкода.
  2. Как взаимодействуют codeи dataразделы договора?
  3. Где я могу найти полную информацию о том, как работает evm?
Добро пожаловать в Ethereum Stack Exchange! Первый вопрос гениален. Однако желательно, чтобы вы могли публиковать отдельные вопросы , а не объединять их в один. Таким образом , это поможет людям, отвечающим на ваш вопрос, а также тем, кто ищет хотя бы один из ваших вопросов. Спасибо!

Ответы (2)

Раздел «данные», упомянутый в желтой бумаге, — это часть, которая следует за инструкцией PUSH, т. е. в желтой бумаге говорится только о выталкиваемых данных. То, что вы видите в выходных данных сборки, является концепцией более высокого уровня.

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

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

Пользователь Reddit любезно опубликовал для вас анализ кода операции:

PUSH1 0x60 PUSH1 0x40 MSTORE

Сохраните 0x60 в ячейке памяти 0x40. Я думаю, что это обычно используется для индексации переменных, если она у вас есть. Я никогда не вдавался в подробности этого

PUSH1 0x6 DUP1

Поместите 2 значения 0x6 в стек. Один должен использоваться как параметр для CODECOPY, другой — как параметр для RETURN. Это размер тела вашего кода. Он состоит из PUSH1 0x60 PUSH1 0x40 MSTORE (опять переменная индексация) STOP (не требует пояснений).

НАЖМИТЕ 0x10

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

НАЖАТЬ1 0x0

Параметр CODECOPY. Это относится к тому, в какое смещение памяти копируется код.

КОДЕКОПИРОВАТЬ

Скопируйте часть кода в память. Основываясь на заданном нами параметре, он запрашивает копирование 6 байтов из 17-го смещения байта (если считать с 1) в ячейку памяти 0.

НАЖАТЬ 0x0 ВОЗВРАТ

RETURN принимает два параметра: количество возвращаемых байтов и возвращаемое смещение в памяти. Поскольку мы создаем контракт, это код, который мы собираемся загрузить. Итак, у нас есть 6 байт (от DUP1 выше), это размер и 0 (смещение памяти, в которое мы скопировали код выше).