🧨 Solidity Security 101: Mistakes I’ll Never Make Again
Jude⚜

Jude⚜ @dhis_is_jj

About: Smart Contracts, Solidity, Trading. My Trifecta

Joined:
Feb 15, 2025

🧨 Solidity Security 101: Mistakes I’ll Never Make Again

Publish Date: May 21
13 1

Solidity is fun… until your smart contract gets wrecked, drained, or exploited and it’s your fault. 😭

I’ve made my fair share of mistakes while building smart contracts, NFT platforms, and DeFi tools on Ethereum. Today, I’m sharing the security blunders I’ve made (so you don’t have to), the "why" behind them, and what to do instead.

** Mistake 1: Trusting msg.sender Without Context**

function withdraw() public {
    require(msg.sender == owner, "Not owner");
    payable(owner).transfer(address(this).balance);
}

Enter fullscreen mode Exit fullscreen mode

❌ What Went Wrong:
I thought only the owner could call this. But if this contract is called from another contract, msg.sender might not be what I expect. Boom!!!....reentrancy or malicious forwarding.

✅ Fix It:
Use tx.origin with care and add checks for contract calls when needed. Even better: use OpenZeppelin’s Ownable and reentrancy guards.

Mistake 2: No Reentrancy Protection

function claimReward() public {
    uint amount = rewards[msg.sender];
    require(amount > 0, "No reward");
    (bool sent, ) = msg.sender.call{value: amount}("");
    require(sent, "Failed");
    rewards[msg.sender] = 0;
}

Enter fullscreen mode Exit fullscreen mode

Classic. This function is re-entrancy prone.

Why It’s Bad:
Before zeroing out the user’s reward, it sends ETH giving malicious contracts a way to call claimReward() again before the balance is reset. Result: they drain the contract.

✅ Fix It:
Use the checks-effects-interactions pattern or import ReentrancyGuard.

function claimReward() public nonReentrant {
    uint amount = rewards[msg.sender];
    require(amount > 0, "No reward");

    rewards[msg.sender] = 0;
    (bool sent, ) = msg.sender.call{value: amount}("");
    require(sent, "Failed");
}

Enter fullscreen mode Exit fullscreen mode

🛡️ Add this modifier: nonReentrant from OpenZeppelin.

Mistake 3: Not Using immutable or constant
I once stored variables like this:

address public owner;
uint256 public fee = 0.01 ether;

Enter fullscreen mode Exit fullscreen mode

Big mistake.

Why It’s Bad:
Storage reads are expensive, especially for values that don’t change.

Use **immutable or constant:**

address public immutable owner;
uint256 public constant FEE = 0.01 ether;

constructor() {
    owner = msg.sender;
}

Enter fullscreen mode Exit fullscreen mode

Saves gas. Makes your contract cleaner.

Mistake 4: Poor Access Control
Ever accidentally leave a function open?

function setAdmin(address _new) public {
    admin = _new;
}

Enter fullscreen mode Exit fullscreen mode

What I Forgot:
Only authorized users should be able to make changes.

Use modifiers:

modifier onlyOwner() {
    require(msg.sender == owner, "Not the owner");
    _;
}

function setAdmin(address _new) public onlyOwner {
    admin = _new;
}

Enter fullscreen mode Exit fullscreen mode

Or better yet: use OpenZeppelin’s AccessControl for roles.

Mistake 5: Writing Gas Refund Loops Without Limits

function deleteAll() public {
    for (uint i = 0; i < users.length; i++) {
        delete users[i];
    }
}

Enter fullscreen mode Exit fullscreen mode

What’s the danger?
Unbounded loops can hit the block gas limit, causing the transaction to fail completely.

Fix It:

  • Let users remove their own data.
  • Use mapping instead of arrays.
  • Or do the work in batches across multiple transactions.

Solidity security is like locking your house in a tough neighborhood. P.S: it’s not optional.
Every little mistake can cost you real ETH, reputation, and peace of mind.

Start building secure habits early:

  • Think like a hacker
  • Read audits & exploit case studies
  • Use OpenZeppelin, Slither, Foundry fuzzing
  • Keep your contracts simple

💬 Your Turn!
Have you made any of these mistakes?
Got a juicy horror story from a smart contract gone wrong?

Drop it in the comments we learn faster together.👇

Until next time
STAY TUNED!!!

Comments 1 total

  • Dun
    DunMay 27, 2025

    Great reminders here—reentrancy and access control bugs really are painful lessons. Thanks for sharing your experience!

Add comment