// Comprehensive Solidity smart contract development skill using Foundry framework. Use for writing, testing, deploying, and auditing Solidity contracts with security-first practices. Also triggers when working with .sol files, Foundry project files (foundry.toml), test files (.t.sol), or smart contract deployment scripts. Example triggers: "Write smart contract", "Create Solidity test", "Deploy contract", "Audit smart contract", "Fix security vulnerability", "Write Foundry test", "Set up Foundry project"
| name | rr-solidity |
| description | Comprehensive Solidity smart contract development skill using Foundry framework. Use for writing, testing, deploying, and auditing Solidity contracts with security-first practices. Also triggers when working with .sol files, Foundry project files (foundry.toml), test files (.t.sol), or smart contract deployment scripts. Example triggers: "Write smart contract", "Create Solidity test", "Deploy contract", "Audit smart contract", "Fix security vulnerability", "Write Foundry test", "Set up Foundry project" |
Comprehensive skill for professional Solidity smart contract development using the Foundry framework. Provides security-first development practices, testing patterns, static analysis integration (Slither, solhint), and deployment workflows for EVM-compatible blockchains.
Automatically activate when:
.sol (Solidity) filesfoundry.toml present)Follow security-first patterns from references/solidity-security.md:
Always implement:
Example contract structure:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
contract MyContract is Ownable, Pausable {
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
error InvalidInput();
error InsufficientBalance();
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event ActionCompleted(address indexed user, uint256 amount);
/*//////////////////////////////////////////////////////////////
STATE VARIABLES
//////////////////////////////////////////////////////////////*/
mapping(address => uint256) public balances;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor() Ownable(msg.sender) {}
/*//////////////////////////////////////////////////////////////
EXTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/
function deposit() external payable whenNotPaused {
if (msg.value == 0) revert InvalidInput();
balances[msg.sender] += msg.value;
emit ActionCompleted(msg.sender, msg.value);
}
function withdraw(uint256 amount) external whenNotPaused {
// CEI Pattern: Checks
if (amount == 0) revert InvalidInput();
if (balances[msg.sender] < amount) revert InsufficientBalance();
// Effects
balances[msg.sender] -= amount;
// Interactions
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
emit ActionCompleted(msg.sender, amount);
}
}
Follow testing patterns from references/foundry-testing.md:
Test structure:
import {Test, console} from "forge-std/Test.sol";
import {MyContract} from "../src/MyContract.sol";
contract MyContractTest is Test {
MyContract public myContract;
address constant OWNER = address(1);
address constant USER = address(2);
function setUp() public {
vm.prank(OWNER);
myContract = new MyContract();
}
// Unit tests
function test_Deposit() public { }
// Edge cases
function test_RevertWhen_ZeroDeposit() public { }
// Fuzz tests
function testFuzz_Deposit(uint256 amount) public { }
// Invariant tests
function invariant_TotalBalanceMatchesContract() public { }
}
Run tests:
forge test # Run all tests
forge test -vvv # Verbose output
forge test --gas-report # Include gas costs
forge coverage # Coverage report
Run comprehensive security checks:
# Static analysis with Slither
slither . --exclude-optimization --exclude-informational
# Linting with solhint
solhint 'src/**/*.sol' 'test/**/*.sol'
# Or use the automated script
bash scripts/check_security.sh
Pre-deployment checklist (from references/solidity-security.md):
Build contracts:
forge build --optimize --optimizer-runs 200
Deploy using script:
// script/Deploy.s.sol
import {Script} from "forge-std/Script.sol";
import {MyContract} from "../src/MyContract.sol";
contract DeployScript is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
MyContract myContract = new MyContract();
console.log("Deployed at:", address(myContract));
vm.stopBroadcast();
}
}
Execute deployment:
# Load environment variables
source .env
# Simulate deployment
forge script script/Deploy.s.sol --rpc-url $SEPOLIA_RPC_URL
# Deploy to testnet
forge script script/Deploy.s.sol \
--rpc-url $SEPOLIA_RPC_URL \
--broadcast \
--verify
# Deploy to mainnet (after audits!)
forge script script/Deploy.s.sol \
--rpc-url $MAINNET_RPC_URL \
--broadcast \
--verify
Test against real deployed contracts:
contract ForkTest is Test {
IERC20 constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
function setUp() public {
vm.createSelectFork("mainnet", 18_000_000);
}
function test_InteractWithRealProtocol() public {
// Test with actual mainnet state
}
}
forge test --fork-url $MAINNET_RPC_URL
Test properties that must always hold:
function invariant_SumOfBalancesEqualsTotalSupply() public {
assertEq(token.totalSupply(), handler.sumOfBalances());
}
Test with randomized inputs:
function testFuzz_Transfer(address to, uint256 amount) public {
vm.assume(to != address(0));
amount = bound(amount, 1, 1000 ether);
// Test with random inputs
}
Key strategies from references/solidity-security.md:
# Verify on Etherscan
forge verify-contract $CONTRACT_ADDRESS \
src/MyContract.sol:MyContract \
--chain-id 1 \
--etherscan-api-key $ETHERSCAN_KEY
# With constructor args
forge verify-contract $CONTRACT_ADDRESS \
src/MyContract.sol:MyContract \
--chain-id 1 \
--etherscan-api-key $ETHERSCAN_KEY \
--constructor-args $(cast abi-encode "constructor(uint256)" 100)
Quick reference from references/foundry-commands.md:
Development:
forge build # Compile contracts
forge test # Run tests
forge test -vvv # Verbose test output
forge coverage # Coverage report
forge fmt # Format code
forge clean # Clean artifacts
Testing:
forge test --match-test test_Transfer # Run specific test
forge test --match-contract MyTest # Run specific contract
forge test --gas-report # Show gas usage
forge test --fork-url $RPC_URL # Fork testing
forge snapshot # Gas snapshot
Deployment:
forge script script/Deploy.s.sol --broadcast
forge create src/MyContract.sol:MyContract --rpc-url $RPC_URL
forge verify-contract $ADDRESS src/MyContract.sol:MyContract
Debugging:
forge test --debug test_MyTest # Interactive debugger
cast run $TX_HASH --debug # Debug transaction
cast run $TX_HASH --trace # Trace transaction
Local node:
anvil # Start local node
anvil --fork-url $MAINNET_RPC_URL # Fork mainnet locally
Static analyzer with 99+ vulnerability detectors:
slither . # Full analysis
slither . --exclude-optimization # Skip optimizations
slither . --exclude-informational # Critical issues only
slither . --checklist # Generate checklist
Linter configured via assets/solhint.config.json:
solhint 'src/**/*.sol' # Lint source
solhint 'test/**/*.sol' # Lint tests
solhint --fix 'src/**/*.sol' # Auto-fix issues
solidity-security.md - Comprehensive security patterns, vulnerabilities, and mitigation strategiesfoundry-testing.md - Testing patterns including fuzzing, invariants, fork testing, and mockingfoundry-commands.md - Complete command reference for forge, cast, and anvilWhen implementing specific functionality, reference these sections:
references/solidity-security.md (AccessControl, Ownable)references/solidity-security.md (CEI pattern)references/foundry-testing.md (fork testing)references/solidity-security.md (optimization strategies)Complete workflow for adding a new feature:
forge test -vvvforge coverageslither .solhint 'src/**/*.sol'forge fmtforge buildforge script script/Deploy.s.sol --broadcastforge verify-contract ...