Security Best Practices
Comprehensive security guidelines for blockchain applications. Protect your smart contracts, user data, and digital assets with enterprise-grade security practices.
Security Domains
Essential security practices organized by domain to ensure comprehensive protection
Smart Contract Security
Best practices for secure smart contract development and deployment
Key Management
Secure key generation, storage, and management practices
Access Control
Authentication, authorization, and identity management
Network Security
Secure communication and network infrastructure
Data Security
Protecting sensitive data at rest and in transit
Monitoring & Incident Response
Security monitoring, logging, and incident response
Security Checklist
Comprehensive security tasks organized by implementation phase
Pre-Deployment
CriticalInfrastructure
CriticalOperational
Compliance
Common Vulnerabilities
Understanding and preventing the most common smart contract vulnerabilities
Reentrancy Attack
CriticalMalicious contract repeatedly calls back into the target contract
Use ReentrancyGuard, follow Checks-Effects-Interactions pattern
function withdraw() external nonReentrant { ... }
Integer Overflow/Underflow
HighArithmetic operations exceed variable limits
Use SafeMath library or Solidity 0.8+ built-in checks
using SafeMath for uint256;
Access Control Bypass
CriticalUnauthorized access to restricted functions
Implement proper access modifiers and role checks
modifier onlyOwner() { require(msg.sender == owner); _; }
Flash Loan Attack
HighManipulation of price oracles using flash loans
Use time-weighted average prices, multiple oracle sources
Use Chainlink or Band Protocol oracles
Front-Running
MediumMEV bots exploit transaction ordering
Use commit-reveal schemes, private mempools
Implement time delays for sensitive operations
Denial of Service
MediumContract becomes unusable due to gas limit issues
Implement gas-efficient patterns, avoid unbounded loops
Use pagination for large data sets
Security Tools
Essential tools for security analysis and vulnerability detection
Static Analysis
Slither
Open SourceSolidity static analysis framework
Mythril
Open SourceSecurity analysis tool for Ethereum
Manticore
Open SourceSymbolic execution tool
Securify
CommercialSecurity scanner for Ethereum
Dynamic Analysis
Echidna
Open SourceProperty-based fuzzing framework
Harvey
CommercialIndustrial-scale fuzzing
Foundry
Open SourceFast testing framework
Hardhat
Open SourceDevelopment environment
Formal Verification
Certora
CommercialFormal verification platform
KEVM
Open SourceK framework for EVM
Dafny
Open SourceVerification-aware language
Coq
Open SourceInteractive theorem prover
Secure Implementation Examples
Production-ready code examples demonstrating security best practices
Secure Token Contract
Example of a security-hardened ERC-20 token with protection mechanisms
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract SecureToken is ERC20, ReentrancyGuard, Pausable, AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
uint256 private constant MAX_SUPPLY = 1000000000 * 10**18; // 1B tokens
// Events for security monitoring
event SecurityEvent(string eventType, address indexed user, uint256 amount);
modifier validAddress(address addr) {
require(addr != address(0), "Invalid address");
require(addr != address(this), "Cannot be contract address");
_;
}
constructor() ERC20("SecureToken", "SECURE") {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(MINTER_ROLE, msg.sender);
_grantRole(PAUSER_ROLE, msg.sender);
}
function mint(address to, uint256 amount)
external
onlyRole(MINTER_ROLE)
validAddress(to)
whenNotPaused
{
require(totalSupply() + amount <= MAX_SUPPLY, "Exceeds max supply");
_mint(to, amount);
emit SecurityEvent("MINT", to, amount);
}
function transfer(address to, uint256 amount)
public
override
nonReentrant
validAddress(to)
whenNotPaused
returns (bool)
{
emit SecurityEvent("TRANSFER", msg.sender, amount);
return super.transfer(to, amount);
}
function transferFrom(address from, address to, uint256 amount)
public
override
nonReentrant
validAddress(to)
whenNotPaused
returns (bool)
{
emit SecurityEvent("TRANSFER_FROM", from, amount);
return super.transferFrom(from, to, amount);
}
function pause() external onlyRole(PAUSER_ROLE) {
_pause();
emit SecurityEvent("PAUSE", msg.sender, 0);
}
function unpause() external onlyRole(PAUSER_ROLE) {
_unpause();
emit SecurityEvent("UNPAUSE", msg.sender, 0);
}
// Emergency function to recover accidentally sent tokens
function emergencyRecover(address token, uint256 amount)
external
onlyRole(DEFAULT_ADMIN_ROLE)
{
require(token != address(this), "Cannot recover own tokens");
IERC20(token).transfer(msg.sender, amount);
emit SecurityEvent("EMERGENCY_RECOVER", msg.sender, amount);
}
}
Access Control System
Multi-level access control with time-locks and emergency procedures
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
contract SecureAccessControl is AccessControl, Pausable {
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE");
struct TimeLock {
uint256 unlockTime;
bytes32 role;
address account;
bool executed;
}
mapping(bytes32 => TimeLock) public timeLocks;
uint256 public constant TIME_LOCK_DELAY = 2 days;
event RoleGrantRequested(bytes32 indexed role, address indexed account, bytes32 lockId);
event RoleGrantExecuted(bytes32 indexed role, address indexed account);
event EmergencyAction(address indexed actor, string action);
modifier onlyEmergency() {
require(hasRole(EMERGENCY_ROLE, msg.sender), "Emergency role required");
_;
}
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(ADMIN_ROLE, msg.sender);
_grantRole(EMERGENCY_ROLE, msg.sender);
}
function requestRoleGrant(bytes32 role, address account)
external
onlyRole(ADMIN_ROLE)
{
bytes32 lockId = keccak256(abi.encodePacked(role, account, block.timestamp));
timeLocks[lockId] = TimeLock({
unlockTime: block.timestamp + TIME_LOCK_DELAY,
role: role,
account: account,
executed: false
});
emit RoleGrantRequested(role, account, lockId);
}
function executeRoleGrant(bytes32 lockId) external onlyRole(ADMIN_ROLE) {
TimeLock storage lock = timeLocks[lockId];
require(!lock.executed, "Already executed");
require(block.timestamp >= lock.unlockTime, "Time lock not expired");
_grantRole(lock.role, lock.account);
lock.executed = true;
emit RoleGrantExecuted(lock.role, lock.account);
}
function emergencyPause() external onlyEmergency {
_pause();
emit EmergencyAction(msg.sender, "PAUSE");
}
function emergencyUnpause() external onlyEmergency {
_unpause();
emit EmergencyAction(msg.sender, "UNPAUSE");
}
function emergencyRevokeRole(bytes32 role, address account)
external
onlyEmergency
{
_revokeRole(role, account);
emit EmergencyAction(msg.sender, "ROLE_REVOKE");
}
function supportsInterface(bytes4 interfaceId)
public
view
override(AccessControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}