Solidity Cursor Rules: Smart Contract Development Guide
Cursor rules for Solidity development covering smart contract patterns, gas optimization, security best practices, testing, and Ethereum blockchain integration.
Overview
Solidity is the primary language for writing smart contracts on the Ethereum blockchain and EVM-compatible networks, powering DeFi protocols and decentralized applications. These cursor rules enforce critical security patterns (like reentrancy guards), meticulous gas optimization, and access control to help AI assistants generate secure, efficient contracts. Whether you're deploying a token standard or a complex decentralized exchange, these rules ensure your code follows the latest security audits and Ethereum developer best practices.
Note:
Enforces reentrancy guards, access control patterns, gas optimization techniques, and OpenZeppelin integration standards.
Rules Configuration
---
description: Enforces best practices for Solidity development, focusing on security patterns, gas optimization, and OpenZeppelin standards. Provides comprehensive guidelines for writing secure, efficient smart contracts with proper context.
globs: **/*.sol
---
# Solidity Best Practices
You are an expert in Solidity development and smart contract security.
You understand modern Solidity development practices, security patterns, and the importance of providing complete context in code generation.
### Context-Aware Code Generation
- Provide contract context including inherited contracts, interfaces, and imports
- Include OpenZeppelin version and Solidity compiler pragma in all contracts
- Generate complete function signatures with proper visibility and modifiers
- Document NatSpec for all public and external functions and state variables
### Security Patterns
- Follow checks-effects-interactions pattern: validate, update state, then call externals
- Use OpenZeppelin ReentrancyGuard on functions that transfer ETH or tokens
- Validate all external inputs with require() statements at function entry
- Use SafeERC20 for token transfers instead of raw .transfer() or .call()
- Avoid tx.origin for authentication; use msg.sender exclusively
- Mark untrusted external calls as potentially unsafe and apply reentrancy protection
### Gas Optimization
- Pack state variables to fit within 32-byte storage slots (uint128 + uint128 together)
- Use calldata over memory for read-only function parameters
- Prefer view/pure functions to avoid state modifications and gas costs
- Use custom errors over string revert messages for cheaper reverts
- Batch operations in loops where possible to reduce total transaction cost
### Access Control & Ownership
- Use OpenZeppelin Ownable for single-owner administrative controls
- Use OpenZeppelin AccessControl for multi-role permission systems
- Apply onlyOwner or specific role modifiers to admin functions
- Implement ownership transfer with two-step pattern for safety
- Use OpenZeppelin Pausable for emergency stop functionality
### Upgradeability
- Use OpenZeppelin UUPS proxy pattern for upgradeable contracts
- Store implementation version in storage for upgrade tracking
- Use initialization functions instead of constructors in proxy contracts
- Test proxy upgrade paths to ensure storage layout compatibility
### Testing
- Write Foundry tests with forge-std for assertions and cheatcodes
- Test all public and external functions for expected behavior and failure cases
- Use fuzz testing with Foundry for edge case coverage
- Run static analysis with Slither before mainnet deployment
- Use Hardhat for integration testing across multiple contract interactions
### Best Practices
- Use Solidity 0.8+ for built-in overflow protection
- Add NatSpec comments (@notice, @param, @return) for all public interfaces
- Use OpenZeppelin contracts for battle-tested implementations
- Emit events for all state changes to support off-chain monitoring
Installation
Create solidity.mdc in your project's .cursor/rules/ directory and paste the configuration above. Cursor and Windsurf both read .cursor/rules/ — Copilot users place it in .github/copilot-instructions.md instead.
Examples
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// TokenVault.sol — Secure transfer with checks-effects-interactions
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract TokenVault is ReentrancyGuard, Ownable {
mapping(address => uint256) public balances;
event Withdrawn(address indexed user, uint256 amount);
function withdraw(uint256 amount) external nonReentrant {
// Check
require(balances[msg.sender] >= amount, "insufficient balance");
// Effect
balances[msg.sender] -= amount;
emit Withdrawn(msg.sender, amount);
// Interaction
(bool ok,) = msg.sender.call{value: amount}("");
require(ok, "transfer failed");
}
}
// Access control with OpenZeppelin Roles
import "@openzeppelin/contracts/access/AccessControl.sol";
contract Governed is AccessControl {
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(PAUSER_ROLE, msg.sender);
}
function pause() external onlyRole(PAUSER_ROLE) { /* ... */ }
}
Related Resources
Related Articles
React Cursor Rules: JSX, Hooks, and Component Patterns
Comprehensive React cursor rules covering component architecture, JSX patterns, hooks usage, accessibility, and testing for maintainable, performant applications.
TypeScript Cursor Rules: AI-Powered Type-Safe Development
TypeScript cursor rules enforcing strict typing, modern patterns, and clean architecture. Help AI generate secure, maintainable code with complete context fast.
Rust Cursor Rules: AI-Powered Development Best Practices
Cursor rules for Rust development enforcing ownership patterns, type safety, async/await practices, and clean code principles with AI assistance for production-ready code.