Fallback Function Explained in Detail
The fallback function runs when no other function matches the calldata. It can also receive Ether if the contract has no receive() function and the fallback is payable.
Fallback functions are common in proxies, routers, and contracts that intentionally handle unknown selectors.
Smart contract example
A proxy may route every unknown selector to an implementation:
fallback() external payable {
address impl = implementation;
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), impl, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
That pattern depends on safe selector routing and safe delegatecall behavior.
Fallback Function in Auditing
Fallback functions are hidden entry points. They can route arbitrary calldata, receive Ether unexpectedly, bypass normal function-level checks, or expose proxy logic through function selectors.
Red flags in code
-
Fallback performs privileged routing or state changes.
-
Fallback target can be changed by weak authority.
-
Payable fallback accepts Ether without accounting.
-
Manual calldata parsing in assembly.
-
Authorization depends on
msg.sigwithout checking target context.
How to test or review it
-
Send unknown selectors and verify the behavior is intended.
-
Use the function selector tool to inspect routed calls.
-
Check whether fallback can receive Ether and how it affects accounting.
-
Review fallback separately from named external functions.
-
For proxies, verify admin selectors, implementation address control, and storage layout.