Интересный нюанс с call вызовом
В Твиттере у одного из аудиторов увидел пост о том, что call вызов может привести к атаке gas griefing через байты, которые он возвращает в качестве ответа. Смотрите, что получается:
(bool success,) = payable(receiver).call{gas: 3000, value: amount}(hex"");
В данном примере после запятой не указан еще один возвращаемый параметр, и это должно выглядеть так:
(bool success, bytes memory data)
Оба варианта верны и часто используются в контрактах. Bytes позволяет вернуть саму ошибку, которая может возникнуть в течении транзакции.
При этому bytes data, которая возвращается из return, будет скопирована в память. И, если размер data будет слишком большой, то стоимость записи в память может превысить лимиты и получится gas griefing.
Аудитор предлагает использовать assembly, который автоматически не копирует возвращаемые значения в память, например:
bool success;
assembly {
success := call(3000, receiver, amount, 0, 0, 0)
}
Не могу точно сказать, что это 100% уязвимость и нужно переходить на assembly всем, так как доказательств в документации я не нашел.
Тем не менее, данный вопрос поднимался не раз на GitHub, вот один из таких примеров.
С обучением разработки смарт контрактов, как в той пословице: "Чем глубже в лес, тем больше дров". Всегда найдется какое-нибудь "но", на которое потом будешь обращать внимание.
#assembly #call
Post #586
311
- 👍 2