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

reentrancy guards · the mutex pattern

SoliaVSThe Reentrancy Reaper
Solia saysA reentrancy guard wraps a function in a mutex flag (NOT_ENTERED → ENTERED → revert if re-entered) — the belt-and-braces companion to checks-effects-interactions.

Even with CEI discipline, complex contracts can have reentrancy paths across functions (one function updates one slot, another reads a stale one). A reentrancy guard is a simple mutex: a state variable starts at NOT_ENTERED, flips to ENTERED on function entry, and reverts if any function annotated with the guard sees it already ENTERED.

OpenZeppelin's ReentrancyGuard uses a single uint slot (cheap with EIP-1153 transient storage). The cost is one warm SSTORE per guarded call. The demo wires up a tiny guard and shows a recursive re-entry being rejected.

Power-ups you unlock

The Reentrancy Reaper attacks — common mistakes

Boss battleImplement a nonReentrant wrapper and show it reverts a recursive call into a guarded function.

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 NOT_ENTERED = 1, ENTERED = 2;
let status = NOT_ENTERED;
function nonReentrant(fn){
  return function(){
    if(status === ENTERED) throw new Error('ReentrancyGuardReentrantCall');
    status = ENTERED;
    try { return fn.apply(null, arguments); } finally { status = NOT_ENTERED; }
  };
}
const protectedFn = nonReentrant(function recurse(d){
  if(d > 0) return protectedFn(d - 1);          // attempts re-entry
  return 'done';
});
const okResult = protectedFn(0);                 // depth 0: no recursion
let blocked = null;
try { protectedFn(1); } catch(e){ blocked = e.message; }
document.getElementById('o').textContent = [
  'direct call (depth=0): ' + okResult,
  're-entrant call (depth=1): ' + (blocked || 'NOT BLOCKED'),
  '',
  'mutex pattern: NOT_ENTERED → ENTERED → revert on re-entry → NOT_ENTERED'
].join('\n');
</script></body></html>
▶ Open the interactive comic issue
‹ Checks-Effects-Interactions · The Safe OrderPull Over Push · The Withdrawal Pattern ›