Install any skill in seconds. Free to start, no credit card required.
Get Started Free →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 p
.claude/skills/microck-rr-solidity/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 163% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 101% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 138% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 163% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 383% | 0% |
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:
solidity// 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:
solidityimport {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:
bashforge test # Run all tests forge test -vvv # Verbose output forge test --gas-report # Include gas costs forge coverage # Coverage report
Run comprehensive security checks:
bash# 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:
bashforge build --optimize --optimizer-runs 200
Deploy using script:
solidity// 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:
bash# 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:
soliditycontract 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 } }
bashforge test --fork-url $MAINNET_RPC_URL
Test properties that must always hold:
solidityfunction invariant_SumOfBalancesEqualsTotalSupply() public { assertEq(token.totalSupply(), handler.sumOfBalances()); }
Test with randomized inputs:
solidityfunction 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:
bash# 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:
bashforge 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:
bashforge 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:
bashforge 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:
bashforge test --debug test_MyTest # Interactive debugger cast run $TX_HASH --debug # Debug transaction cast run $TX_HASH --trace # Trace transaction
Local node:
bashanvil # Start local node anvil --fork-url $MAINNET_RPC_URL # Fork mainnet locally
Static analyzer with 99+ vulnerability detectors:
bashslither . # Full analysis slither . --exclude-optimization # Skip optimizations slither . --exclude-informational # Critical issues only slither . --checklist # Generate checklist
Linter configured via assets/solhint.config.json:
bashsolhint '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 ...| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 11,218 | 6,887 | -39% | 1 | 1 | 0% | 1,989 | 4,006 | +101% | 0 | 0 | — |
case-02 | pass→pass | 10,517 | 6,782 | -36% | 1 | 1 | 0% | 1,756 | 4,172 | +138% | 0 | 0 | — |
case-03 | pass→pass | 8,493 | 7,448 | -12% | 1 | 1 | 0% | 1,613 | 4,250 | +163% | 0 | 0 | — |
case-04 | fail→pass | 8,643 | 5,450 | -37% | 1 | 1 | 0% | 1,412 | 3,713 | +163% | 0 | 0 | — |
case-05 | pass→pass | 4,583 | 4,220 | -8% | 1 | 1 | 0% | 744 | 3,597 | +383% | 0 | 0 | — |
case-06 | pass→pass | 7,469 | 3,550 | -52% | 1 | 1 | 0% | 1,314 | 3,513 | +167% | 0 | 0 | — |
case-07 | pass→pass | 15,618 | 12,973 | -17% | 1 | 1 | 0% | 2,565 | 5,134 | +100% | 0 | 0 | — |
case-08 | pass→pass | 3,657 | 3,693 | +1% | 1 | 1 | 0% | 533 | 3,499 | +556% | 0 | 0 | — |
case-09 | pass→pass | 6,151 | 2,092 | -66% | 1 | 1 | 0% | 1,080 | 3,149 | +192% | 0 | 0 | — |
case-10 | pass→pass | 6,526 | 3,196 | -51% | 1 | 1 | 0% | 1,192 | 3,438 | +188% | 0 | 0 | — |
case-11 | pass→pass | 5,575 | 2,600 | -53% | 1 | 1 | 0% | 955 | 3,244 | +240% | 0 | 0 | — |
case-12 | pass→pass | 4,400 | 4,395 | -0% | 1 | 1 | 0% | 761 | 3,681 | +384% | 0 | 0 | — |
case-13 | pass→pass | 5,095 | 3,068 | -40% | 1 | 1 | 0% | 878 | 3,439 | +292% | 0 | 0 | — |
case-14 | pass→pass | 4,042 | 3,495 | -14% | 1 | 1 | 0% | 648 | 3,424 | +428% | 0 | 0 | — |
case-15 | pass→pass | 9,731 | 6,181 | -36% | 1 | 1 | 0% | 1,853 | 3,986 | +115% | 0 | 0 | — |
case-16 | pass→pass | 12,507 | 15,670 | +25% | 1 | 1 | 0% | 2,022 | 5,893 | +191% | 0 | 0 | — |
case-17 | pass→pass | 6,577 | 3,914 | -40% | 1 | 1 | 0% | 1,107 | 3,470 | +213% | 0 | 0 | — |
case-18 | pass→pass | 10,632 | 6,304 | -41% | 1 | 1 | 0% | 1,786 | 3,968 | +122% | 0 | 0 | — |
case-19 | pass→pass | 3,173 | 2,371 | -25% | 1 | 1 | 0% | 451 | 3,185 | +606% | 0 | 0 | — |
case-20 | pass→pass | 2,998 | 2,729 | -9% | 1 | 1 | 0% | 419 | 3,215 | +667% | 0 | 0 | — |
case-21 | pass→pass | 14,630 | 13,745 | -6% | 1 | 1 | 0% | 2,392 | 5,454 | +128% | 0 | 0 | — |
case-22 | pass→pass | 2,143 | 2,249 | +5% | 1 | 1 | 0% | 354 | 3,155 | +791% | 0 | 0 | — |
case-23 | pass→pass | 11,492 | 11,959 | +4% | 1 | 1 | 0% | 2,259 | 5,199 | +130% | 0 | 0 | — |
case-24 | pass→pass | 25,785 | 9,035 | -65% | 1 | 1 | 0% | 2,975 | 4,521 | +52% | 0 | 0 | — |
case-25 | pass→pass | 14,593 | 12,096 | -17% | 1 | 1 | 0% | 2,934 | 5,367 | +83% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 25 cases were attempted. The headline lift of +4 percentage points is the difference between those two pass rates over the 25 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.