Secure Smart Contract Development

Security best practices for Solidity smart contracts, DeFi protocols, and blockchain applications.

Irreversible Consequences

Smart contract vulnerabilities can result in immediate, irreversible financial losses. Security must be the top priority.

Overview

Smart contracts handle billions in value and cannot be easily patched after deployment. This guide covers critical security practices.

Security Checklist

  • Follow Checks-Effects-Interactions pattern
  • Use ReentrancyGuard for all external calls
  • Implement proper access control with OpenZeppelin
  • Use Solidity 0.8+ for built-in overflow protection
  • Never rely on single-source price oracles
  • Implement time-locks for admin functions
  • Write comprehensive test coverage
  • Get professional audits before mainnet deployment

Preventing Reentrancy

Reentrancy attacks have caused billions in losses. Use the Checks-Effects-Interactions pattern and ReentrancyGuard.

Solidity
1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.19;
3
4import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
5
6contract SecureVault is ReentrancyGuard {
7 mapping(address => uint256) public balances;
8
9 // Checks-Effects-Interactions pattern + ReentrancyGuard
10 function withdraw(uint256 amount) external nonReentrant {
11 // 1. CHECKS: Validate conditions
12 require(balances[msg.sender] >= amount, "Insufficient balance");
13
14 // 2. EFFECTS: Update state BEFORE external call
15 balances[msg.sender] -= amount;
16
17 // 3. INTERACTIONS: External call last
18 (bool success, ) = msg.sender.call{value: amount}("");
19 require(success, "Transfer failed");
20 }
21}

Access Control

Use OpenZeppelin's access control contracts for role-based permissions.

Solidity
1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.19;
3
4import "@openzeppelin/contracts/access/AccessControl.sol";
5import "@openzeppelin/contracts/security/Pausable.sol";
6
7contract SecureToken is AccessControl, Pausable {
8 bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
9 bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
10
11 constructor() {
12 _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
13 }
14
15 function mint(address to, uint256 amount)
16 external
17 onlyRole(MINTER_ROLE)
18 whenNotPaused
19 {
20 _mint(to, amount);
21 }
22
23 function pause() external onlyRole(PAUSER_ROLE) {
24 _pause();
25 }
26}

Safe Arithmetic

Solidity 0.8+ includes built-in overflow protection. For older versions, use SafeMath.

Solidity
1// Solidity 0.8+ has built-in overflow checks
2pragma solidity ^0.8.19;
3
4contract SafeMath {
5 // Automatic revert on overflow/underflow
6 function safeAdd(uint256 a, uint256 b) public pure returns (uint256) {
7 return a + b; // Reverts on overflow
8 }
9
10 // Be careful with division order for precision
11 function calculateFee(uint256 amount, uint256 feePercent)
12 public
13 pure
14 returns (uint256)
15 {
16 // Multiply BEFORE divide to preserve precision
17 return (amount * feePercent) / 10000;
18 }
19}

Oracle Security

Never rely on spot prices from DEXs. Use time-weighted averages or decentralized oracles like Chainlink.

Solidity
1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.19;
3
4import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
5
6contract SecurePriceFeed {
7 AggregatorV3Interface internal priceFeed;
8 uint256 public constant STALENESS_THRESHOLD = 1 hours;
9
10 constructor(address _priceFeed) {
11 priceFeed = AggregatorV3Interface(_priceFeed);
12 }
13
14 function getLatestPrice() public view returns (int256) {
15 (
16 uint80 roundId,
17 int256 price,
18 uint256 startedAt,
19 uint256 updatedAt,
20 uint80 answeredInRound
21 ) = priceFeed.latestRoundData();
22
23 // Validate oracle data
24 require(price > 0, "Invalid price");
25 require(updatedAt > 0, "Round not complete");
26 require(
27 block.timestamp - updatedAt < STALENESS_THRESHOLD,
28 "Stale price data"
29 );
30 require(answeredInRound >= roundId, "Stale round");
31
32 return price;
33 }
34}

Security Testing

Use Bloodhound for automated security analysis alongside manual testing.

Bash
1# Run Bloodhound security scan
2bloodhound scan contracts/ --mode apex
3
4# Run with specific Solidity patterns
5bloodhound scan contracts/ --language solidity --severity critical,high
6
7# Generate audit report
8bloodhound scan contracts/ --mode apex --report audit-report.pdf
9
10# Foundry fuzzing
11forge test --fuzz-runs 10000
12
13# Slither static analysis
14slither contracts/
Always Get Professional Audits

Before deploying contracts that handle significant value, always get professional security audits from reputable firms.