# The Solid(ity) Misadventures: A Dev’s Guide to Smart Contract Survival **Published by:** [fabian](https://paragraph.com/@fabiancreative-operations.group/) **Published on:** 2025-06-04 **Categories:** solidity, code, evm **URL:** https://paragraph.com/@fabiancreative-operations.group/the-solidity-misadventures-a-devs-guide-to-smart-contract-survival ## Content So, you want to write a smart contract. Great! You’ve got dreams of decentralization, passive income, and maybe even a token named after your cat. But before you deploy and accidentally mint 2 billion extra tokens or lose everything in a reentrancy blackhole… sit down. Breathe. 1. Integer Overflow & UnderflowAh yes, the good old days (pre-Solidity 0.8.0) when subtracting 1 from 0 gave you 2⁵⁶-1 and nobody blinked. Rookie mistake:// Solidity <0.8.0 uint8 balance = 0; balance -= 1; // Surprise! balance = 255 Use SafeMath, unless you're into heart attacks:=0.8.0 has built-in checks. But let's pretend it's 2019 again: using SafeMath for uint256; uint256 balance = 0; balance = balance.sub(1); // Revert with "SafeMath: subtraction overflow" ">// Solidity >=0.8.0 has built-in checks. But let's pretend it's 2019 again: using SafeMath for uint256; uint256 balance = 0; balance = balance.sub(1); // Revert with "SafeMath: subtraction overflow" What it feels like debugging overflow bugs:"Why does this token supply say 1.1 quattuordecillion?"2. Reentrancy Attacks – The Smart Contract Yo-YoSay you’re building a bank contract. (Bold move. Auditors are already sweating.) Here’s how NOT to do it: 0); (bool sent, ) = msg.sender.call{value: balances[msg.sender]}(""); // 😬 External call first? require(sent, "Failed to send Ether"); balances[msg.sender] = 0; // Too late, bro. } ">Editfunction withdraw() public { require(balances[msg.sender] > 0); (bool sent, ) = msg.sender.call{value: balances[msg.sender]}(""); // 😬 External call first? require(sent, "Failed to send Ether"); balances[msg.sender] = 0; // Too late, bro. } Attacker’s dream:Editfallback() external payable { victim.withdraw(); // Yo-yo time! } How to fix it (and keep your ETH): 0); balances[msg.sender] = 0; // Update balance first (bool sent, ) = msg.sender.call{value: amount}(""); require(sent, "Transfer failed"); } ">// Check-Effects-Interactions pattern function withdraw() public nonReentrant { uint256 amount = balances[msg.sender]; require(amount > 0); balances[msg.sender] = 0; // Update balance first (bool sent, ) = msg.sender.call{value: amount}(""); require(sent, "Transfer failed"); } Bonus tip: "@openzeppelin/contracts/security/ReentrancyGuard.sol"; Be smart. Be guarded. Like a smart contract Kevin Costner.3. Uninitialized Storage Pointers — The Forgotten MappingsYou think you’re clever. You write:function storeData() public { MyStruct storage s; // Uh-oh. s.value = 42; } This doesn’t "create" a new struct. This says: "Hey, modify random storage slot zero!" Result: You may overwrite important contract data like the owner address, or your dignity. Do this instead:MyStruct storage s = myStructs[msg.sender]; // Actual location 4. DoS (Denial of Service) by GaslightImagine this:function sendRewards() public { for (uint i = 0; i < users.length; i++) { users[i].transfer(1 ether); // expensive AF } } User list gets long. Function dies of gas exhaustion. R.I.P. Fix:Use pull over push method.Limit batch size.Add checkpointing logic.Or just don’t build Ethereum into a to-do list app.5. Unchecked External Calls – Trust Issues 101ExternalService external = ExternalService(externalAddress); external.doSomethingCritical(); // Checks? Nah. YOLO. This is how rug pulls happen. Better:(bool success, bytes memory data) = externalAddress.call(abi.encodeWithSignature("doSomethingCritical()")); require(success, "External call failed"); if (abi.decode(data, (bool)) != true) { revert("That external contract is sus"); } Or use interfaces and only call verified contracts. You wouldn't give your wallet to a guy in an alley with "TotallyNotAScam.eth" on his jacket, right?Final ThoughtSmart contracts are like vending machines: automatic, immutable, and occasionally prone to spitting out flaming toads when you mess up. So, use require, modifier, and humility liberally. Always test like your ETH depends on it — because it does.Cheat Sheet 📝ProblemFixOverflow/UnderflowUse SafeMath or Solidity ≥ 0.8.0ReentrancyChecks-Effects-Interactions / nonReentrantUninitialized PointersAlways assign storage vars explicitlyDoS via gasAvoid unbounded loops / Use batchingUnchecked CallsValidate return values / Use trusted interfacesMay your gas be cheap and your audits thorough. Deploy responsibly, you must. ## Publication Information - [fabian](https://paragraph.com/@fabiancreative-operations.group/): Publication homepage - [All Posts](https://paragraph.com/@fabiancreative-operations.group/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@fabiancreative-operations.group): Subscribe to updates ## Optional - [Collect as NFT](https://paragraph.com/@fabiancreative-operations.group/the-solidity-misadventures-a-devs-guide-to-smart-contract-survival): Support the author by collecting this post - [View Collectors](https://paragraph.com/@fabiancreative-operations.group/the-solidity-misadventures-a-devs-guide-to-smart-contract-survival/collectors): See who has collected this post