slide 28 · security
Smart contract vulnerabilities
Exploit , /underflow and 'private' data — then patch them.
- 1Run the exploit
- 2Read what the attacker did
- 3Apply the fix and re-run
send coins to another player
waiting for another player to join this room… open this page in a second tab or share the link with the class.
- no transfers yet — be the first to pay a classmate.
Vulnerable contract
1mapping(address => uint) public balances;23function withdraw() external {4 uint bal = balances[msg.sender];5 require(bal > 0);6 // ❌ interaction BEFORE effect7 (bool ok,) = msg.sender.call{value: bal}("");8 require(ok);9 balances[msg.sender] = 0; // never reached in time10}
Exploit trace
Re-entrancy
msg.sender.call hands execution to the attacker's contract while your storage is still stale. Its receive() function calls withdraw() again, and again, each time passing the balance check. Fix: checks-effects-interactions ordering, plus a nonReentrant mutex.
Seen in the wild: The DAO, 2016 — ~3.6M ETH drained, and the reason Ethereum Classic exists. Defence in depth: checks-effects-interactions, audited OpenZeppelin bases, Solidity 0.8+, Slither and Mythril in CI, Foundry fuzz and invariant tests, a bug bounty, and a timelocked pause switch for when all of that still misses one.