freecoding.school100% FREE · NO SIGNUP
The EVM CoreISSUE #30 of 48

fallback · receive · low-level calls

SoliaVSThe Reentrancy Reaper
Solia saysSolidity dispatches calls by selector; receive() handles plain ETH, fallback() handles everything unknown, and low-level call/staticcall/delegatecall reach across the type system.

A contract receiving a call decides what to do via dispatch. If msg.data is empty and ETH is attached, the receive() function runs (or revert if it does not exist). If the selector matches a function, that function runs. If nothing matches, the fallback() function runs (or revert). Low-level calls — call, staticcall, delegatecall — bypass type checks: you build the calldata yourself and get back raw bytes plus a success flag.

Use receive() for plain ETH deposits, fallback() for proxy patterns (forward unknown selectors to a logic contract), and low-level calls when interacting with unknown or precompiled contracts. The demo dispatches three different incoming calls.

Power-ups you unlock

The Reentrancy Reaper attacks — common mistakes

Boss battleDispatch three incoming calls (plain ETH, known selector, unknown selector) and identify which handler runs.

Example code

<!doctype html><html><head><meta charset="utf-8"></head>
<body style="background:#06040d;color:#e6e0ff;font-family:monospace;padding:20px"><pre id="o"></pre>
<script>
const known = ['0xa9059cbb', '0x70a08231', '0x23b872dd'];   // transfer, balanceOf, transferFrom
function dispatch(call){
  if((!call.calldata || call.calldata === '0x') && call.value > 0) return 'receive()  — plain ETH, no calldata';
  const selector = (call.calldata || '0x').slice(0, 10);
  if(known.includes(selector)) return 'function  — selector ' + selector + ' matched';
  return 'fallback() — no matching selector for ' + selector;
}
const calls = [
  { calldata:'0x', value:1, label:'1 ETH, empty calldata' },
  { calldata:'0xa9059cbb000...', value:0, label:'calldata starts 0xa9059cbb' },
  { calldata:'0xdeadbeef000...', value:0, label:'calldata starts 0xdeadbeef' }
];
document.getElementById('o').textContent = calls.map(c =>
  c.label.padEnd(34) + '→ ' + dispatch(c)
).join('\n');
</script></body></html>
▶ Open the interactive comic issue
‹ Libraries · Embedded Vs Linked · Using-ForEvents · Indexed Topics · Log Decoding ›