Функция "fallback()" вызывается в том случае, если относительно смарт-контракта бала вызвана транзакция с неизвеным именем функции.
Это нужно для того чтобы, например, в случае, если на смарт-контракт придет транзакция с вызовом функции, которой нет, она не откатится, а покажет ошибку, которая была описана в "fallback".
Проще говоря, если к нам придет транзакция, которая запросит функцию возврата денег, а она не прописана у нас, то в "fallback" можно отловить этот момент и показать ошибку.
#fallback #функции #function
Это нужно для того чтобы, например, в случае, если на смарт-контракт придет транзакция с вызовом функции, которой нет, она не откатится, а покажет ошибку, которая была описана в "fallback".
Проще говоря, если к нам придет транзакция, которая запросит функцию возврата денег, а она не прописана у нас, то в "fallback" можно отловить этот момент и показать ошибку.
#fallback #функции #function
🔥1
Особенности fallback функций
Если fallback() указан как payable, то он может принимать Ether.
Особенность отправляющих Ether функций transfer и send в том, что у них есть ограничение - инициированная ими транзакция не должна расходовать больше, чем 2300 gas. Поэтому, если внутри fallback реализована какая-то сложная логика (вызвать еще какие-то функции, записать storage и т.д.) (при поступлении Ether с помощью transfer или send), то это будет стоить больше, чем 2300 и транзакция откатится.
Максимум на что хватит газа в такой ситуации внутри fallback - это на emit event.
При этом, если эфир отправляется с помощью call вызовов, то есть возможность повышения лимита газа, и тогда в fallback функция не откатит транзакцию.
Будьте аккуратны с этим, и всегда дополняйте fallback другими функциями, которые могут принимать деньги, например receive.
#hint #fallback #receive
Если fallback() указан как payable, то он может принимать Ether.
Особенность отправляющих Ether функций transfer и send в том, что у них есть ограничение - инициированная ими транзакция не должна расходовать больше, чем 2300 gas. Поэтому, если внутри fallback реализована какая-то сложная логика (вызвать еще какие-то функции, записать storage и т.д.) (при поступлении Ether с помощью transfer или send), то это будет стоить больше, чем 2300 и транзакция откатится.
Максимум на что хватит газа в такой ситуации внутри fallback - это на emit event.
При этом, если эфир отправляется с помощью call вызовов, то есть возможность повышения лимита газа, и тогда в fallback функция не откатит транзакцию.
Будьте аккуратны с этим, и всегда дополняйте fallback другими функциями, которые могут принимать деньги, например receive.
#hint #fallback #receive
Немного о фантомных функциях
Уже несколько раз в различных статьях видел упоминания о фантомных функциях в контрактах. И вот еще одна прекрасная статья, рассказывающая о том, что в контрактах токенов могут быть подобные функции, которые могут привести к взлому.
Сама статья на английском языке, но ее суть в том, что если в контракте токена, как например в WETH, нет функции permit(), но есть fallback(), то вызывая из вашего контракта weth.premit() - транзакция не откатится с ошибкой.
Это может быть уязвимостью, как было в примере с AnySwap/MultiChain.
Подробнее читаем в статье.
#phantom #fallback #permit
Уже несколько раз в различных статьях видел упоминания о фантомных функциях в контрактах. И вот еще одна прекрасная статья, рассказывающая о том, что в контрактах токенов могут быть подобные функции, которые могут привести к взлому.
Сама статья на английском языке, но ее суть в том, что если в контракте токена, как например в WETH, нет функции permit(), но есть fallback(), то вызывая из вашего контракта weth.premit() - транзакция не откатится с ошибкой.
Это может быть уязвимостью, как было в примере с AnySwap/MultiChain.
Подробнее читаем в статье.
#phantom #fallback #permit
❤3
Solidity hints. Часть 20
Всех с новой рабочей неделей и сегодня мы разберем довольно интересный пункт из репо, который звучит как:
The data returned from fallback function will not be ABI-encoded. Instead it will be returned without modifications (not even padding) WTF
что в переводе:
Данные, возвращаемые функцией fallback, не будут кодироваться ABI. Вместо этого они будут возвращены без изменений (даже без падинга) ОМБ
Думаю, для начала напомню, что такое паддинг.
Допустим мы создали байтовый массив с фиксированной длиной bytes32. Если мы запишем туда значение, которое будет меньше 32 байтов, то его конец будет заполнен нулями, например:
bytes32: 0x5b38da6a701c568545dcfcb03fcb875f56beddc4000000000000000000000000
Тут мы записали адрес 5b38da6a701c568545dcfcb03fcb875f56beddc4, и так как размерность была 32, то оставшееся место заняли нули. Это и называется паддингом.
Он разделяется на два вида:
Right-padded - к нему относят такие типы данных как, string, bytes and bytesN (N - указание на размерность).
Left-padded - intN / uintN, address and другие типы.
Другими словами, в одном случае нули будут добавляться в конец, в другом - в начало.
Теперь перейдем к самим fallback функциям.
Во многих источниках в сети, я встречал следующие описания:
1. Она являются неименованными функциями.
2. Она не может принимать аргументы.
3. Она не может ничего возвращать.
3. В смарт-контракте может быть только одна такая функция.
4. Обязательно должна быть external.
5. Для приема Эфира должна иметь модификатор payable.
6. Ограничено лимитом в 2300 газа, если ее вызывают другие функции.
7. Исполняется, когда в контракте не найдена вызываемая функция.
И если 5 пунктов верны для всех случаем с fallback, то 2 и 3 не совсем верны, так как есть следующая форма функции:
fallback (bytes calldata input) external [payable] returns (bytes memory output)
т.е. они и принимает, и возвращает некоторые данные. Об этой форме и говорится в разбираемом пункте. Эта фишка появилась в функции в версии 0.7.6
На словах объяснить будет немного сложно, поэтому будет проще посмотреть примеры возвращаемых значений в Ремиксе в контрактах:
Сначала разворачиваются контракты TestFallbackInputOutput и Counter, а затем FallbackInputOutput от адреса Counter.
После деплоя вызываете getTestData() для получения банных для отправки, а затем test() с адресом FallbackInputOutput.
В первый раз попробуйте с простым return, а после с return abi.encode(res), и в логах посмотрите, какие данные возвращаются.
В первом случае вернуться незашифрованные данные, о чем и говорится в пункте. Если хотите как-то контролировать их получение, то нужно дополнительно использовать abi.encode для этого.
#fallback #output
Всех с новой рабочей неделей и сегодня мы разберем довольно интересный пункт из репо, который звучит как:
The data returned from fallback function will not be ABI-encoded. Instead it will be returned without modifications (not even padding) WTF
что в переводе:
Данные, возвращаемые функцией fallback, не будут кодироваться ABI. Вместо этого они будут возвращены без изменений (даже без падинга) ОМБ
Думаю, для начала напомню, что такое паддинг.
Допустим мы создали байтовый массив с фиксированной длиной bytes32. Если мы запишем туда значение, которое будет меньше 32 байтов, то его конец будет заполнен нулями, например:
bytes32: 0x5b38da6a701c568545dcfcb03fcb875f56beddc4000000000000000000000000
Тут мы записали адрес 5b38da6a701c568545dcfcb03fcb875f56beddc4, и так как размерность была 32, то оставшееся место заняли нули. Это и называется паддингом.
Он разделяется на два вида:
Right-padded - к нему относят такие типы данных как, string, bytes and bytesN (N - указание на размерность).
Left-padded - intN / uintN, address and другие типы.
Другими словами, в одном случае нули будут добавляться в конец, в другом - в начало.
Теперь перейдем к самим fallback функциям.
Во многих источниках в сети, я встречал следующие описания:
1. Она являются неименованными функциями.
2. Она не может принимать аргументы.
3. Она не может ничего возвращать.
3. В смарт-контракте может быть только одна такая функция.
4. Обязательно должна быть external.
5. Для приема Эфира должна иметь модификатор payable.
6. Ограничено лимитом в 2300 газа, если ее вызывают другие функции.
7. Исполняется, когда в контракте не найдена вызываемая функция.
И если 5 пунктов верны для всех случаем с fallback, то 2 и 3 не совсем верны, так как есть следующая форма функции:
fallback (bytes calldata input) external [payable] returns (bytes memory output)
т.е. они и принимает, и возвращает некоторые данные. Об этой форме и говорится в разбираемом пункте. Эта фишка появилась в функции в версии 0.7.6
На словах объяснить будет немного сложно, поэтому будет проще посмотреть примеры возвращаемых значений в Ремиксе в контрактах:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract FallbackInputOutput {
address immutable target;
constructor(address _target) {
target = _target;
}
fallback(bytes calldata data) external payable returns (bytes memory) {
(bool ok, bytes memory res) = target.call{value: msg.value}(data);
//require(ok, "call failed");
return res;
//return abi.encode(res);
}
}
contract Counter {
uint256 public count;
function get() external view returns (uint256) {
return count;
}
}
contract TestFallbackInputOutput {
event Log(bytes res);
function test(address _fallback, bytes calldata data) external {
(bool ok, bytes memory res) = _fallback.call(data);
require(ok, "call failed");
emit Log(res);
}
function getTestData() external pure returns (bytes memory) {
return
(abi.encodeCall(Counter.get, ()));
}
}
Сначала разворачиваются контракты TestFallbackInputOutput и Counter, а затем FallbackInputOutput от адреса Counter.
После деплоя вызываете getTestData() для получения банных для отправки, а затем test() с адресом FallbackInputOutput.
В первый раз попробуйте с простым return, а после с return abi.encode(res), и в логах посмотрите, какие данные возвращаются.
В первом случае вернуться незашифрованные данные, о чем и говорится в пункте. Если хотите как-то контролировать их получение, то нужно дополнительно использовать abi.encode для этого.
#fallback #output
🤯1