address nameReg = 0x72ba7d8e73fe8eb666ea66babc8116a41bfb10e2;
nameReg.call("register", "MyName"); //1
nameReg.call(bytes4(sha3("fun(uint256)")), a); //2
if(!nameReg.call.value(10)){throw;} //3
Здесь говорится,
Кроме того, для взаимодействия с контрактами, которые не соответствуют ABI, предоставляется вызов функции, который принимает произвольное количество аргументов любого типа. Эти аргументы дополняются до 32 байтов и объединяются. Единственным исключением является случай, когда первый аргумент закодирован ровно в четыре байта. В этом случае он не дополняется, чтобы разрешить использование здесь сигнатур функций.
Solidity call
— это низкоуровневый интерфейс для отправки сообщения контракту. Он возвращается false
, если подвызов встречает исключение, в противном случае он возвращает true
. Не существует понятия законного вызова, если он компилируется, это действительный Solidity.
nameReg.call("register", "MyName")
это сообщение, которое передает определенные байты в nameReg. Для байтов см.: Понимание вызова стиля nameReg.call("register", "MyName") между контрактами.
nameReg.call(bytes4(sha3("fun(uint256)")), a)
— это сообщение, которое вызовет функцию с именем fun
(если nameReg соответствует ABI) и передаст ей необработанные данные без дополнений a
(вам нужно a
сначала правильно заполнить до 32 байтов, если вы хотите, чтобы поведение соответствовало ABI ) . Для uint256
использования левого заполнения. ).
Для 3 contract.call.value(...)(...)
это способ добавить эфир при вызове контракта. if(!nameReg.call.value(10)()){throw;}
является примером обработки случая сбоя подвызова. Обратите внимание на дополнительные круглые скобки value(10)()
, которые вызывают резервную функцию.
call
является низкоуровневым интерфейсом, и проще вызвать функцию напрямую, nameReg.fun(a)
чем во втором примере. Прямой вызов также является типобезопасным и позволяет использовать возвращаемое значение fun
.
Тьяден Хесс
"register"
и"MyName"
дополняются до 32 байтов, тогда как в случае 2a
объединяются непосредственно с 4-байтовымbytes4(sha3("fun(uint256)"))
пользователь 2284570
эт
call
не возвращает возвращаемое значение контрактной функции: он возвращает только то, столкнулось ли функция с исключением или нет.Люк Хатчисон
(bool success, bool returnBytes) = addr.call{...}(abi.encodeWithSignature(...), ...)
это новый рекомендуемый способ (1) вызова функций без броска, если функция не может быть вызвана, и (2) отправки платежа оплачиваемым функциям. Так что я почти уверен, что комментарий Крисета относитсяcall
только к более старым версиям.эт