Smart contract security basics: never trust the caller
Reentrancy, missing access control, and unchecked assumptions account for a surprising amount of lost money.
Hammad Iqbal
Software Engineer
Every public function on a contract can be called by anyone, including someone who has read your code line by line and is looking for the one assumption you made. Most serious contract bugs are not clever. They are ordinary mistakes that happen to guard real money.
- Check who is calling, every time it matters.
- Update your own state before sending money out.
- Do not rely on the frontend to enforce a rule.
Access control
Functions that move funds or change settings must check the caller. A missing owner or role check is the simplest bug and one of the most costly. Writing the allowed caller next to every sensitive function makes gaps easy to spot in review.
Reentrancy
When a contract sends funds to another contract, that contract can call back before the first function has finished. If your balance is updated after the transfer, the callback can withdraw again. The standard defense is checks, effects, interactions: validate first, update your state second, and make the external call last. A reentrancy guard adds a second layer.
The frontend is not a security boundary
Buttons can be hidden in the UI, but the contract is reachable directly. Any rule that matters, such as deadlines, limits, and permissions, has to be enforced on-chain. Treat the interface as a convenience for honest users only.
Assume a hostile caller, check permissions on-chain, and make external calls last.
Have a project this kind of thinking applies to?
Tell me what you're building — I read every message myself.