---
name: microck/rr-solidity
source: https://app.decimal.ai/s/microck-rr-solidity@1/SKILL.md
source_sha256: 3142a08bede1
---

# Solidity Development with Foundry

## Overview

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.

## When to Use This Skill

Automatically activate when:
- Working with `.sol` (Solidity) files
- User mentions smart contracts, blockchain, Web3, DeFi, or Ethereum
- Foundry project detected (`foundry.toml` present)
- User requests contract deployment, testing, or security auditing
- Working with forge, cast, or anvil commands
- Implementing ERC standards (ERC20, ERC721, ERC1155, etc.)


## Development Workflow

### 1. Write Secure Contracts

Follow security-first patterns from `references/solidity-security.md`:

**Always implement:**
- Checks-Effects-Interactions (CEI) pattern
- Access control (Ownable, AccessControl)
- Input validation
- Emergency pause mechanisms
- Pull over push for payments
- Custom errors for gas efficiency

**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);
    }
}
```

### 2. Write Comprehensive Tests

Follow testing patterns from `references/foundry-testing.md`:

**Test structure:**

```solidity
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:**

```bash
forge test              # Run all tests
forge test -vvv         # Verbose output
forge test --gas-report # Include gas costs
forge coverage          # Coverage report
```

### 3. Security Analysis

**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`):
- [ ] Reentrancy protection implemented
- [ ] Access controls on privileged functions
- [ ] Input validation on all external functions
- [ ] Emergency pause mechanism
- [ ] External calls follow CEI pattern
- [ ] Events emitted for state changes
- [ ] Gas optimizations applied
- [ ] Test coverage >90%
- [ ] Slither analysis passed
- [ ] solhint checks passed
- [ ] Professional audit for mainnet

### 4. Build and Deploy

**Build contracts:**

```bash
forge 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
```

## Advanced Testing Patterns

### Mainnet Forking

Test against real deployed contracts:

```solidity
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
    }
}
```

```bash
forge test --fork-url $MAINNET_RPC_URL
```

### Invariant Testing

Test properties that must always hold:

```solidity
function invariant_SumOfBalancesEqualsTotalSupply() public {
    assertEq(token.totalSupply(), handler.sumOfBalances());
}
```

### Fuzz Testing

Test with randomized inputs:

```solidity
function testFuzz_Transfer(address to, uint256 amount) public {
    vm.assume(to != address(0));
    amount = bound(amount, 1, 1000 ether);
    // Test with random inputs
}
```

## Gas Optimization

Key strategies from `references/solidity-security.md`:

1. **Storage packing** - Group uint8/uint16/etc in single slots
2. **uint256 for counters** - Native EVM word size
3. **calldata over memory** - For function parameters
4. **Events over storage** - Log data instead of storing
5. **Custom errors** - More gas-efficient than strings
6. **Immutable/constant** - For unchanging values

## Contract Verification

```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)
```

## Common Commands Reference

Quick reference from `references/foundry-commands.md`:

**Development:**
```bash
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:**
```bash
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:**
```bash
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:**
```bash
forge test --debug test_MyTest           # Interactive debugger
cast run $TX_HASH --debug                # Debug transaction
cast run $TX_HASH --trace                # Trace transaction
```

**Local node:**
```bash
anvil                                    # Start local node
anvil --fork-url $MAINNET_RPC_URL       # Fork mainnet locally
```

## Security Tools Integration

### Slither

Static analyzer with 99+ vulnerability detectors:

```bash
slither .                                # Full analysis
slither . --exclude-optimization         # Skip optimizations
slither . --exclude-informational        # Critical issues only
slither . --checklist                    # Generate checklist
```

### solhint

Linter configured via `assets/solhint.config.json`:

```bash
solhint 'src/**/*.sol'                   # Lint source
solhint 'test/**/*.sol'                  # Lint tests
solhint --fix 'src/**/*.sol'             # Auto-fix issues
```

## Resources


### references/
- `solidity-security.md` - Comprehensive security patterns, vulnerabilities, and mitigation strategies
- `foundry-testing.md` - Testing patterns including fuzzing, invariants, fork testing, and mocking
- `foundry-commands.md` - Complete command reference for forge, cast, and anvil

## Best Practices Summary

1. **Security First**: Always implement CEI pattern, access controls, and input validation
2. **Test Coverage**: Aim for >90% coverage with unit, fuzz, and invariant tests
3. **Static Analysis**: Run Slither and solhint before every deployment
4. **Gas Optimization**: Apply after security, never at the expense of safety
5. **Documentation**: Use NatSpec comments for all public/external functions
6. **Audit**: Professional audit required for mainnet deployment
7. **Verification**: Verify all contracts on Etherscan post-deployment
8. **Emergency**: Include pause mechanisms for critical contracts

## Common Patterns to Reference

When implementing specific functionality, reference these sections:

- **ERC20 tokens** - Use OpenZeppelin's implementation
- **Access control** - `references/solidity-security.md` (AccessControl, Ownable)
- **Upgradeable contracts** - OpenZeppelin's proxy patterns
- **Reentrancy protection** - `references/solidity-security.md` (CEI pattern)
- **Testing external protocols** - `references/foundry-testing.md` (fork testing)
- **Gas optimization** - `references/solidity-security.md` (optimization strategies)
- **Randomness** - Use Chainlink VRF, never block.timestamp alone
- **Oracles** - Use Chainlink price feeds for production

## Workflow Example

Complete workflow for adding a new feature:

1. **Write contract** following security patterns
2. **Write tests** with >90% coverage
3. **Run tests**: `forge test -vvv`
4. **Check coverage**: `forge coverage`
5. **Run Slither**: `slither .`
6. **Run solhint**: `solhint 'src/**/*.sol'`
7. **Format code**: `forge fmt`
8. **Build**: `forge build`
9. **Deploy to testnet**: `forge script script/Deploy.s.sol --broadcast`
10. **Verify**: `forge verify-contract ...`
11. **Get audit** (for mainnet)
12. **Deploy to mainnet** after audit approval