An unchecked external call is a Solidity bug where a contract uses a low-level call (call, send, delegatecall) but ignores its boolean return value. Unlike a normal function call, these do not revert on failure, they return false. If the contract does not check, it proceeds as though a failed transfer or call succeeded, leaving balances and state inconsistent and sometimes letting value disappear or logic break. The fix is to check every low-level call’s return value (or use a safe wrapper). It maps to SWC-104.
What it is
Solidity has two call styles. A normal call (token.transfer(...) on a contract that reverts) bubbles up failures. But the low-level primitives, address.call(...), address.send(...), delegatecall, do not revert when the call fails; they return a `bool` success flag that the developer must check.
An unchecked external call ignores that flag, so a failed send or call is silently treated as success, and execution continues with the contract’s state now wrong.
How it works and example
A withdrawal that zeroes the balance regardless of whether the send worked:
function withdraw(uint amount) public {
balances[msg.sender] -= amount;
msg.sender.send(amount); // return value ignored
}
If send fails (out of gas, a reverting recipient), the funds are not transferred, but the balance was already reduced, the user loses funds, or, in other patterns, accounting drifts so the contract can be drained. Failed external calls that are assumed to succeed also break multi-step logic. Documented for defensive context.
How to defend
- Check the return value of every low-level call:
(bool ok,) = addr.call{...}(""); require(ok);. - Prefer higher-level calls or safe wrappers (a SafeERC20-style library) that revert on failure.
- Handle the failure path explicitly, do not assume success.
- Combine with checks-effects-interactions so a failed external call does not leave inconsistent state.
- Audit for any
call/send/delegatecallwhose result is discarded.
References
- [1]SWC Registry: Smart Contract Weakness Classification(SWC Registry)
- [2]Solidity docs: Security considerations(Solidity)
- [3]MITRE CWE-252: Unchecked Return Value(MITRE CWE)