Видимость значения параметра

Видно ли значение параметра метода контракта в блокчейне? На Etherscan в информации о tx есть поле «Входные данные», в котором говорится:

Двоичные данные, которые сформировали вход транзакции, либо входные данные, если это был вызов сообщения, либо инициализация контракта, если это было создание контракта.

Это то, что я ищу?

Ответы (1)

Да, эта информация общедоступна и генерируется следующим образом:

Освоение Ethereum — передача полезной нагрузки данных в EOA или контракт

Когда ваша транзакция содержит данные, она, скорее всего, адресована контрактному адресу. Это не означает, что вы не можете отправить полезную нагрузку данных в EOA — это полностью допустимо в протоколе Ethereum. Однако в этом случае интерпретация данных зависит от кошелька, который вы используете для доступа к EOA. Он игнорируется протоколом Ethereum. Большинство кошельков также игнорируют любые данные, полученные в транзакции с EOA, который они контролируют. Возможно, в будущем появятся стандарты, которые позволят кошелькам интерпретировать данные так же, как это делают контракты, что позволит транзакциям вызывать функции, работающие внутри пользовательских кошельков. Критическое отличие заключается в том, что любая интерпретация полезной нагрузки данных EOA не регулируется правилами консенсуса Ethereum, в отличие от исполнения контракта.

А пока предположим, что ваша транзакция доставляет данные на адрес контракта. В этом случае данные будут интерпретироваться EVM как вызов контракта. Большинство контрактов используют эти данные более конкретно как вызов функции, вызывая именованную функцию и передавая ей любые закодированные аргументы.

Полезная нагрузка данных, отправляемая в ABI-совместимый контракт (которым, как вы можете предположить, являются все контракты), представляет собой шестнадцатеричное сериализованное кодирование:

Селектор функций

Первые 4 байта хэша Keccak-256 прототипа функции. Это позволяет контракту однозначно определить, какую функцию вы хотите вызвать.

Аргументы функции

Аргументы функции, закодированные в соответствии с правилами для различных элементарных типов, определенных в спецификации ABI.

В solidity_faucet_example мы определили функцию для снятия средств:

function withdraw(uint withdraw_amount) public {

Прототип функции определяется как строка, содержащая имя функции, за которой следуют типы данных каждого из ее аргументов, заключенные в круглые скобки и разделенные запятыми. Имя функции здесь — remove, и она принимает единственный аргумент — uint (который является псевдонимом для uint256), поэтому прототипом remove будет:

withdraw(uint256)

Давайте посчитаем хэш Keccak-256 этой строки:

> web3.sha3("withdraw(uint256)"); 
'0x2e1a7d4d13322e7b96f9a57413e1525c250fb7a9021cf91d1540d5b69f16a49f'

Первые 4 байта хеша — 0x2e1a7d4d. Это значение нашего «селектора функций», которое сообщит контракту, какую функцию мы хотим вызвать.

Далее давайте вычислим значение, которое будет передано в качестве аргумента remove_amount. Хотим вывести 0.01 эфира. Давайте закодируем это в шестнадцатеричное сериализованное 256-битное целое число без знака с обратным порядком байтов, выраженное в wei:

> withdraw_amount = web3.toWei(0.01, "ether");
'10000000000000000'
> withdraw_amount_hex = web3.toHex(withdraw_amount);
'0x2386f26fc10000'

Теперь мы добавляем селектор функций к количеству (дополненному до 32 байт):

2e1a7d4d000000000000000000000000000000000000000000000000002386f26fc10000

Это полезная нагрузка данных для нашей транзакции, вызывающая функцию снятия и запрашивающая 0,01 эфира в качестве суммы снятия.