Входные данные транзакции Ethereum — необязательное поле, которое может содержать произвольные данные. При стандартном вызове функции по ABI эти байты имеют определённую структуру: селектор функции, за которым следуют закодированные аргументы. Чтобы интерпретировать такую структуру, нужна соответствующая схема интерфейса.
При чтении полезно разделять три вопроса: какие байты присутствуют, как выбранная схема их интерпретирует и какие выводы пока не подтверждены. Пустое поле, узнаваемый селектор и декодированное число отвечают лишь на отдельные части этой задачи.
Что содержит поле input
Документация Ethereum о транзакциях описывает входные данные как необязательное поле для произвольных данных. Это широкое определение существенно: содержимое поля не обязано соответствовать соглашению ABI о вызовах функций. Сначала следует определить, какие именно байты представлены, и лишь затем приписывать им имя функции или тип аргумента.
Для массивов байтов Ethereum JSON-RPC использует шестнадцатеричную запись с префиксом 0x: каждому байту соответствуют две шестнадцатеричные цифры. Правила кодирования JSON-RPC различают такое представление DATA и формат числовых величин. При чтении входных данных важно сохранять это различие, даже если обе записи внешне начинаются одинаково.
В представлении массива байтов запись 0x означает пустую последовательность: после префикса нет ни одного байта данных. Это не кодировка числовой величины ноль. Такую запись следует описывать как пустые входные данные, а не как число, которое ещё предстоит расшифровать. Здесь мы устанавливаем содержимое поля, не определяя по нему назначение транзакции.
Как связаны селектор и аргументы
Спецификация ABI контрактов Solidity отводит первые четыре байта стандартных данных вызова функции под её селектор. Закодированные аргументы, если они есть, начинаются с пятого байта. Эта структура не означает, что каждой функции нужны аргументы, и не описывает любую произвольную последовательность во входном поле.
Селектор состоит из первых четырёх байтов хеша Keccak-256 канонической сигнатуры функции. Сигнатура включает имя функции и заключённый в круглые скобки список типов параметров. Типы разделяются запятыми без пробелов и записываются в каноническом представлении ABI. Конкретные значения аргументов в эту сигнатуру не входят.
Для вымышленной учебной функции с одним параметром uint256 предположим каноническую сигнатуру record(uint256). В этом упражнении она задаёт имя функции и тип параметра. Конкретное значение, например 6, относится к области закодированных аргументов. Значение селектора для этой вымышленной функции здесь не вычисляется и не утверждается.
Размечая стандартный вызов ABI, обозначайте селектор и область аргументов отдельно. Рядом указывайте описание интерфейса, на основании которого интерпретируете байты. Тогда будет видно, где заканчивается наблюдение над самой последовательностью и начинается её прочтение по выбранной схеме. Это особенно полезно при обсуждении учебного примера с заранее заданными условиями.
Зачем для декодирования нужна схема ABI
Кодировка ABI не является самоописываемой: для декодирования требуется схема, задающая структуру и типы данных. Подходящий ABI контракта предоставляет эту информацию, но конкретный JSON-файл — лишь один из способов представить необходимые сведения о типах.
Об этом легко забыть, когда инструмент показывает знакомое имя функции. Документация Ethereum иллюстрирует неоднозначность селекторов на примере 0xa9059cbb: в разборе упоминаются несколько известных функций-кандидатов для этого селектора. Пример подтверждает возможность нескольких кандидатов. Он не устанавливает, что у каждого селектора обязательно есть несколько известных совпадений.
Поэтому результат поиска по селектору следует считать определением возможного кандидата, пока интерфейс контракта назначения не установлен. Для учебного разбора запишите, откуда взята схема. Если типы просто заданы условием, оставьте это допущение видимым. Если схема неизвестна, сохраните неопределённость типов вместо того, чтобы представлять правдоподобную подпись как подтверждённую.
Гипотетический аргумент со значением 6
Рассмотрим гипотетическое упражнение с тремя явными допущениями: входные данные корректно закодированы как стандартный вызов ABI, селектор соответствует предполагаемой функции, а функция принимает ровно один аргумент uint256. После четырёх байтов селектора в условии приведено следующее слово аргумента:
0000000000000000000000000000000000000000000000000000000000000006
Это слово содержит 31 нулевой байт и завершающий байт 06. В стандартной кодировке ABI поддерживаемые беззнаковые целые числа представлены 32-байтовыми значениями с порядком от старшего байта к младшему и дополнением нулевыми байтами слева. Правило относится именно к этим целочисленным типам в стандартном ABI; оно не служит универсальным способом чтения любых типов или произвольных входных данных.
Вывод зависит от условий: заданная схема определяет слово после селектора как uint256, а правило кодирования беззнаковых целых даёт значение 6. Эту интерпретацию вместе обосновывают положение аргумента, схема типов и правило кодирования. Само окончание последовательности ещё не заменяет этих предпосылок.
Теперь уберём схему из условия. Поскольку кодировка не является самоописываемой, одного слова, заканчивающегося на 06, недостаточно, чтобы установить тип uint256. Дополнительные сведения об интерфейсе могли бы подтвердить тип, но сами байты не предоставляют недостающую предпосылку. Этот пример также не подтверждает, что какая-либо реальная транзакция состоялась или была исполнена.
Что позволяет установить пустое поле input
Пустое поле содержит ноль байтов, а стандартному селектору ABI нужны четыре байта. Из этих двух предпосылок следует явный вывод: пустые входные данные не содержат стандартного селектора функции ABI. Это вывод о наличии байтов. Тип аккаунта назначения он не устанавливает.
Отдельно документация Ethereum указывает, что транзакция, направленная на аккаунт контракта, исполняет код контракта. Это общее положение не определяет конкретный путь обработки и не подтверждает успешность исполнения. Чтобы использовать его в разборе, принадлежность адреса назначения контракту должна быть установлена либо явно задана условием.
Во втором гипотетическом упражнении зададим два условия: получателем является аккаунт контракта, а входные данные пусты. Отсутствие байтов селектора и правило об исполнении кода по адресу контракта могут применяться одновременно. Вывод ограничен: из отсутствия селектора не следует отсутствие исполнения кода контракта. Для определения конкретного пути обработки или результата потребовались бы дополнительные сведения.
Проверочный список для чтения входных данных
- Определите представление. Рассматривайте поле как массив байтов DATA, отдельно от правил записи числовых величин.
- Проверьте, пусто ли поле. Зафиксируйте
0xкак ноль входных байтов, не приписывая этой записи тип получателя или результат исполнения. - Установите соглашение о кодировании. Применяйте разбиение на селектор и аргументы только при обоснованном допущении о стандартном вызове ABI.
- Укажите схему. Запишите сведения об интерфейсе, на которые опираетесь, либо явно обозначьте гипотетические типы параметров.
- Сохраняйте оговорки для имён-кандидатов. Поиск по селектору может быть неоднозначным и сам по себе не устанавливает интерфейс назначения.
- Объясняйте каждый вывод. Связывайте декодированное значение с положением аргумента, схемой типов и правилом кодирования.
Эти вопросы помогают точно описывать прочитанные байты. Проверочный список упорядочивает интерпретацию, но не удостоверяет безопасность контракта. Ссылки на источники показывают основание объяснения, не устанавливая безопасность конкретного взаимодействия.
Учебный материал подготовлен с помощью ИИ. Гипотетические примеры объясняют декодирование входных данных и не содержат рекомендаций о финансовых действиях.
Материал по смежной теме: ABI контракта Ethereum: как читать интерфейс и понимать его ограничения.