TGViewer
Из Solidity в AI и дальше Из Solidity в AI и дальше @solidityset · 2.49K subscribers
Post #1247 934
Низкоуровневый вызов и высокоуровневый вызов в Solidity

Контракт в Solidity может вызывать другие контракты двумя способами: через интерфейс контракта, что считается высокоуровневым вызовом, или с помощью метода call, что является низкоуровневым подходом.

Несмотря на то, что оба метода используют опкод CALL, Solidity обрабатывает их по-разному.

В этой статье мы сравним их: почему низкоуровневый вызов никогда не возвращается, в то время как высокоуровневый вызов может вернуться, и почему низкоуровневый вызов по пустому адресу считается успешным, а высокоуровневый вызов возвращается при вызове несуществующего контракта.

Почему низкоуровневый вызов (или вызов delegatecall) никогда не возвращается, а вызов через интерфейс контракта может?

Прежде чем объяснить, почему, обратимся к документации Solidity, в которой рассматривается этот вопрос.

Когда исключения происходят в подвызове (sub-call), они «всплывают» - «bubble up» - (т. е. исключения отбрасываются) автоматически, если только они не пойманы в операторе try/catch. Исключением из этого правила являются send и низкоуровневые функции call, delegatecalll и staticcall: они возвращают false в качестве первого возвращаемого значения в случае исключения вместо того, чтобы «bubble up».

Ниже покажу оба вызова, чтобы сравнить их поведение. В примере я использую метод call, но те же принципы можно распространить и на delegatecall.

Вызывающий может вызвать ops() в Called двумя способами. Обратите внимание, что ops() всегда возвращается:

pragma solidity ^0.8.0;

contract Caller {

// first call to ops()
function callByCall(address _address) public returns (bool success) {
(success, ) = _address.call(abi.encodeWithSignature("ops()"));
}

// second call to ops()
function callByInterface(address _address) public {
Called called = Called(_address);
called.ops();
}
}
contract Called {

// ops() always reverts
function ops() public {
revert();
}
}


Несмотря на то, что оба метода используются для вызова одной и той же функции, и оба метода используют опкод CALL, компилятор solidity генерирует байткод для обработки случаев реверта по-разному. Выполнение обеих функций в рамках контракта Caller покажет, что Caller.callByInterface вернется, а Caller.callByCall - нет.

На уровне EVM опкод CALL возвращает булево число, указывающее, был ли вызов успешным или нет, и помещает это возвращение в стек. Сам опкод не вызывает возврата.

Когда вызов выполняется через интерфейс контракта, Solidity обрабатывает это возвращаемое значение за нас. Он явно проверяет, является ли возвращаемое значение ложным, и инициирует возврат, если только вызов не был сделан внутри блока try/catch.

Однако при использовании низкоуровневых вызовов нам нужно вручную обрабатывать возвращаемый булевый символ и при необходимости явно инициировать возврат.

contract Caller {

//...
function callByCall(address address) public returns (bool success) {
(success, ) = address.call(abi.encodeWithSignature("ops()"));
if (!success) {
revert("Something went wront");
}
}
//...
}


P.S. Разница между высокоуровневым и низкоуровневым вызовом показана на скрине.

#highlevel #lowlevel #call
  • ❤ 5
  • 👍 1
More from @solidityset
  1. Sep 22, 2026Какой язык программирования учить сейчас? На днях в Твиттере увидел небольшой пост о разви…
  2. Sep 18, 2026Интересная модель Jev Буквально пару дней назад в Твиттере многие начали обсуждение новой…
  3. Sep 14, 2026Графы повсюду Если вы также следите за новостями в мире ИИ, то наверняка уже все чаще встр…
  4. Sep 10, 2026GTA6, Cyberleek, блокчейн и безопасность Увидел несколько постов (тут и тут) про Cyberleek…
  5. Sep 9, 2026Работа с чистой энергией Дисклеймер Сегодня ава и название канала, наконец, поменялись. Я…
  6. Sep 9, 2026Channel name was changed to «Из Solidity в AI и дальше»
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →