# Solidity Security Best Practices 2026 — Complete Guide
Smart contract security paramount है क्योंकि code immutable है और bugs billions in losses का कारण बन चुके हैं। इस comprehensive guide में, हम cover करेंगे common vulnerabilities, prevention techniques और 2026 industry best practices।
Why Security Matters
Famous hacks:
- The DAO: $60M (2016)
- Parity Multisig: $150M (2017)
- Poly Network: $600M (2021)
- Ronin Bridge: $625M (2022)
- Euler Finance: $197M (2023)
Key lesson: एक single bug catastrophic हो सकता है।
Security Principles
1. Checks-Effects-Interactions Pattern
हमेशा follow करें:
// ✅ SECURE
function withdraw(uint256 amount) public {
// 1. Checks
require(balances[msg.sender] >= amount, "Insufficient balance");
// 2. Effects
balances[msg.sender] -= amount;
// 3. Interactions
(bool success,) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
}
// ❌ VULNERABLE (Reentrancy)
function withdraw(uint256 amount) public {
require(balances[msg.sender] >= amount);
(bool success,) = msg.sender.call{value: amount}(""); // Interaction before effect!
balances[msg.sender] -= amount; // Too late
}
2. Use ReentrancyGuard
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract Secure is ReentrancyGuard {
function withdraw(uint256 amount) public nonReentrant {
// Protected
}
}
Common Vulnerabilities
1. Reentrancy
Example attack:
contract Victim {
mapping(address => uint256) public balances;
function withdraw() public {
uint256 amount = balances[msg.sender];
(bool success,) = msg.sender.call{value: amount}(""); // ⚠️ Dangerous
require(success);
balances[msg.sender] = 0; // Too late!
}
}
contract Attacker {
Victim victim;
constructor(Victim _victim) {
victim = _victim;
}
receive() external payable {
if (address(victim).balance >= 1 ether) {
victim.withdraw(); // Reenter!
}
}
function attack() public payable {
require(msg.value >= 1 ether);
victim.deposit{value: 1 ether}();
victim.withdraw(); // Start attack
}
}
Prevention:
// Solution 1: Checks-Effects-Interactions
function withdraw() public {
uint256 amount = balances[msg.sender];
balances[msg.sender] = 0; // Effect first
(bool success,) = msg.sender.call{value: amount}("");
require(success);
}
// Solution 2: ReentrancyGuard
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract Secure is ReentrancyGuard {
function withdraw() public nonReentrant {
// Safe
}
}
// Solution 3: Pull over Push
mapping(address => uint256) public pendingWithdrawals;
function withdraw() public {
uint256 amount = pendingWithdrawals[msg.sender];
pendingWithdrawals[msg.sender] = 0;
(bool success,) = msg.sender.call{value: amount}("");
require(success);
}
2. Integer Overflow/Underflow
Pre-Solidity 0.8.0:
uint8 x = 255;
x = x + 1; // Overflows to 0 (pre-0.8.0)
Solidity 0.8.0+: Automatic checks!
uint8 x = 255;
x = x + 1; // Reverts automatically ✅
Unchecked blocks:
function increment(uint256 x) public pure returns (uint256) {
unchecked {
return x + 1; // ⚠️ No overflow check! Use carefully
}
}
// Safe usage: when overflow impossible
for (uint256 i = 0; i < length; ) {
// ...
unchecked { ++i; } // i can't overflow in realistic scenarios
}
3. Access Control
❌ Vulnerable:
function mint(address to, uint256 amount) public {
balances[to] += amount; // कोई भी call कर सकता है!
}
✅ Secure:
address public owner;
modifier onlyOwner() {
require(msg.sender == owner, "Not authorized");
_;
}
function mint(address to, uint256 amount) public onlyOwner {
balances[to] += amount;
}
// Better: OpenZeppelin Ownable
import "@openzeppelin/contracts/access/Ownable.sol";
contract Secure is Ownable {
function mint(address to, uint256 amount) public onlyOwner {
// Safe
}
}
// Advanced: Role-Based Access Control
import "@openzeppelin/contracts/access/AccessControl.sol";
contract Advanced is AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER");
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
// Only addresses with MINTER_ROLE can call
}
}
4. Front-Running
Problem: Miners transactions reorder कर सकते हैं।
Example:
// Vulnerable DEX
function swap(uint256 amountIn) public {
uint256 price = getCurrentPrice(); // ⚠️ Frontrunnable
// ...
}
Mitigations:
// 1. Commit-Reveal scheme
mapping(address => bytes32) public commits;
function commit(bytes32 hash) public {
commits[msg.sender] = hash;
}
function reveal(uint256 value, bytes32 salt) public {
require(keccak256(abi.encodePacked(value, salt)) == commits[msg.sender]);
// Process value
}
// 2. Minimum output amount
function swap(uint256 amountIn, uint256 minAmountOut) public {
uint256 amountOut = calculateOutput(amountIn);
require(amountOut >= minAmountOut, "Slippage exceeded");
// Swap
}
// 3. Flashbots (off-chain)
5. tx.origin Authentication
❌ NEVER use:
function withdraw() public {
require(tx.origin == owner); // ⚠️ Phishable!
}
Attack:
// Attacker deploys malicious contract
contract Phishing {
Victim victim;
function attack() public {
victim.withdraw(); // tx.origin = victim owner (who called attack)
}
}
✅ Always use msg.sender:
function withdraw() public {
require(msg.sender == owner); // ✅ Safe
}
6. Delegatecall to Untrusted Contracts
❌ Dangerous:
function execute(address target, bytes memory data) public {
(bool success,) = target.delegatecall(data); // ⚠️ target आपका storage control कर सकता है!
}
✅ Safe:
// Only delegatecall to trusted contracts
address public immutable trustedImplementation;
function execute(bytes memory data) public {
trustedImplementation.delegatecall(data); // Safe
}
7. Uninitialized Storage Pointers
❌ Vulnerable (older Solidity):
struct User {
uint256 balance;
bool active;
}
function bug() public {
User user; // ⚠️ Points to storage slot 0!
user.balance = 100; // Overwrites storage!
}
✅ Modern Solidity prevents this।
8. Floating Pragma
❌ Risky:
pragma solidity ^0.8.0; // ⚠️ Any 0.8.x version
✅ Lock version:
pragma solidity 0.8.20; // ✅ Exact version
9. Block Timestamp Manipulation
❌ Don't rely on for randomness:
function random() public view returns (uint256) {
return uint256(keccak256(abi.encodePacked(block.timestamp))); // ⚠️ Predictable!
}
✅ Use Chainlink VRF:
import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
contract Random is VRFConsumerBase {
// Proper randomness
}
✅ Timestamps for time windows:
// OK for approximate time (±15 seconds tolerance)
require(block.timestamp >= startTime, "Not started yet");
10. Unchecked External Calls
❌ Ignoring return values:
token.transfer(recipient, amount); // ⚠️ Ignores return value
✅ Check return:
bool success = token.transfer(recipient, amount);
require(success, "Transfer failed");
// Or use SafeERC20
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
using SafeERC20 for IERC20;
token.safeTransfer(recipient, amount); // Reverts on failure
Security Tools
1. Slither (Static Analysis)
pip3 install slither-analyzer
slither contract.sol
Detects:
- Reentrancy
- Uninitialized variables
- Dangerous delegatecalls
- 70+ other issues
2. Mythril (Symbolic Execution)
myth analyze contract.sol
3. Echidna (Fuzzing)
contract TestContract {
// Invariant: always true
function echidna_balance_positive() public view returns (bool) {
return balance >= 0;
}
}
4. Foundry Invariant Testing
function invariant_totalSupply() public {
assertEq(token.totalSupply(), INITIAL_SUPPLY);
}
5. Manticore (Advanced)
Symbolic execution for deep analysis।
Audit Checklist
Pre-Audit
- [ ] Code complete और stable
- [ ] All tests passing (95%+ coverage)
- [ ] Slither run किया बिना critical issues
- [ ] Documentation complete
- [ ] Access control reviewed
- [ ] External dependencies audited
Audit Process
- [ ] Professional audit firm hire करें
- [ ] Code freeze during audit
- [ ] सभी findings address करें
- [ ] Re-audit if major changes
Post-Audit
- [ ] Audit report public करें
- [ ] Bug bounty program launch करें
- [ ] Monitoring setup (Tenderly, Defender)
- [ ] Emergency pause mechanism ready
- [ ] Multisig for admin functions
- [ ] Timelock for upgrades
Best Practices Summary
Code Quality
Access Control
External Interactions
Testing
Deployment
Security Resources
Learning
- Ethernaut — Security challenges
- Damn Vulnerable DeFi — DeFi hacking
- Solingo Security Track — 60+ exercises
Audit Firms
- Trail of Bits
- OpenZeppelin
- Consensys Diligence
- Quantstamp
- Certora
- ChainSecurity
Bug Bounties
- Immunefi — Largest Web3 bounty platform
- Code4rena — Competitive audits
- Sherlock — Audit contests
निष्कर्ष
Smart contract security एक journey है, destination नहीं। Continuous learning और vigilance essential हैं।
Key takeaways:
- Checks-Effects-Interactions हमेशा
- ReentrancyGuard use करें
- Professional audit करवाएं
- Comprehensive testing
- Monitoring और emergency procedures
- Community bug bounties
Security में invest करना billions save कर सकता है।
अगला कदम: Solingo पर security challenges practice करें!
---
अतिरिक्त Resources:
- SWC Registry — Vulnerability classification
- Rekt News — Latest hacks analyzed