Low-Level Call Explained in Detail
Low-level calls interact with addresses without normal Solidity interface checks. They usually return (bool success, bytes memory data) and leave error handling to the caller.
They are powerful, but easy to misuse.
Smart contract example
(bool ok, bytes memory data) = target.call(payload);
require(ok, "call failed");
Ignoring ok can make the contract continue after a failed call.
Low-Level Call in Auditing
Low-level calls often appear in proxies, routers, plugins, callbacks, ETH transfers, and generic execution systems. They can introduce reentrancy, unchecked failures, arbitrary target execution, and confusing return data.
Auditors check the target, payload, success handling, and state-update order.
Red flags in code
-
successis ignored. -
Target or calldata is user-controlled without restrictions.
-
ETH is sent before state updates.
-
Return data length and type are not checked.
-
delegatecallis used wherecallwas intended.
How to test or review it
-
Test target success, revert, false return, and malformed return data.
-
Use malicious receivers to test reentrancy.
-
Review call ordering against checks-effects-interactions.
-
Confirm allowed targets and selectors are constrained.
-
Decode and validate return data where it affects state.