Claude-skill-registry contract-patterns

Common Solidity design patterns and implementations for secure smart contract development. Use when implementing standard functionality like access control, upgradeability, or token standards.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/contract-patterns" ~/.claude/skills/majiayu000-claude-skill-registry-contract-patterns && rm -rf "$T"
manifest: skills/data/contract-patterns/SKILL.md
source content

Contract Patterns Skill

This skill provides battle-tested patterns and examples for common smart contract functionality.

When to Use

Use this skill when:

  • Implementing access control mechanisms
  • Creating upgradeable contracts
  • Building token contracts (ERC20, ERC721, ERC1155)
  • Adding pausability to contracts
  • Protecting against reentrancy attacks
  • Following established security patterns

Pattern Categories

1. Access Control Patterns

See

./patterns/access-control.md
for detailed documentation.

Common patterns:

  • Ownable - Single owner with privileged access
  • AccessControl - Role-based access control (RBAC)
  • Multisig - Multiple signatures required for actions
  • Timelock - Delayed execution for critical functions

When to use:

  • Ownable: Simple contracts with single admin
  • AccessControl: Complex permissions with multiple roles
  • Multisig: High-value contracts requiring consensus
  • Timelock: Governance and critical upgrades

2. Upgradeable Contract Patterns

See

./patterns/upgradeable-contracts.md
for detailed documentation.

Common patterns:

  • Transparent Proxy - Separate admin and user logic
  • UUPS (Universal Upgradeable Proxy Standard) - Upgrade logic in implementation
  • Beacon Proxy - Multiple proxies sharing same implementation
  • Diamond Pattern (EIP-2535) - Multi-facet proxy for large contracts

When to use:

  • Transparent: When admin and user separation is critical
  • UUPS: Gas-efficient upgrades, upgrade logic in implementation
  • Beacon: Deploying many instances of same logic
  • Diamond: Large contracts exceeding size limits

3. Pausable Pattern

See

./patterns/pausable.md
for detailed documentation.

Purpose: Emergency stop mechanism to pause contract functionality

When to use:

  • Contracts handling user funds
  • Contracts that may need emergency stops
  • Contracts under active development/monitoring

Key features:

  • Pause/unpause functionality
  • Restricted to authorized roles
  • Graceful degradation of functionality

4. Reentrancy Guard

See

./patterns/reentrancy-guard.md
for detailed documentation.

Purpose: Prevent reentrancy attacks in functions that make external calls

When to use:

  • Functions that transfer ETH
  • Functions that call external contracts
  • Functions that modify state after external calls

Implementation:

  • Checks-Effects-Interactions pattern
  • ReentrancyGuard modifier
  • Mutex locks

5. Token Standards

See

./patterns/token-standards.md
for detailed documentation.

ERC20 - Fungible tokens

  • Standard interface for tokens like USDC, DAI
  • Transfer, approve, transferFrom functionality
  • See
    ./examples/ERC20-example.sol

ERC721 - Non-fungible tokens (NFTs)

  • Unique tokens with individual ownership
  • Metadata support
  • See
    ./examples/ERC721-example.sol

ERC1155 - Multi-token standard

  • Batch operations for fungible and non-fungible tokens
  • Gas-efficient for multiple token types
  • See
    ./examples/ERC1155-example.sol

Integration with Code Principles

These patterns follow the code-principles from the foundation plugin:

  • DRY: Inherit from OpenZeppelin contracts instead of reimplementing
  • SOLID: Single responsibility for each pattern/module
  • KISS: Use simplest pattern that meets requirements
  • Security First: Battle-tested implementations over custom code

Note: Solidity-specific security concerns take precedence over general software principles.

OpenZeppelin Contracts

Most patterns are best implemented using OpenZeppelin contracts:

# Install OpenZeppelin
forge install OpenZeppelin/openzeppelin-contracts
# or
npm install @openzeppelin/contracts

Available contracts:

  • @openzeppelin/contracts/access/Ownable.sol
  • @openzeppelin/contracts/access/AccessControl.sol
  • @openzeppelin/contracts/security/Pausable.sol
  • @openzeppelin/contracts/security/ReentrancyGuard.sol
  • @openzeppelin/contracts/token/ERC20/ERC20.sol
  • @openzeppelin/contracts/token/ERC721/ERC721.sol
  • @openzeppelin/contracts/token/ERC1155/ERC1155.sol
  • @openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol
  • @openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol

Pattern Selection Guide

NeedPatternComplexityGas CostSecurity
Single adminOwnableLowLowMedium
Multiple rolesAccessControlMediumMediumHigh
Emergency stopPausableLowLowHigh
Prevent reentrancyReentrancyGuardLowLowCritical
Fungible tokensERC20LowLowHigh
NFTsERC721MediumMediumHigh
Multi-tokenERC1155HighLowHigh
Simple upgradesUUPSMediumLowHigh
Admin separationTransparent ProxyMediumMediumHigh
Multiple instancesBeacon ProxyHighLowHigh
Large contractsDiamondVery HighMediumMedium

Best Practices

  1. Prefer OpenZeppelin - Use audited implementations over custom code
  2. Combine patterns carefully - Test interactions between patterns
  3. Follow initialization patterns - Use proper constructor/initializer for upgradeable contracts
  4. Test thoroughly - Each pattern has unique security considerations
  5. Document deviations - If customizing standard patterns, document why
  6. Keep it simple - Use simplest pattern that meets requirements
  7. Security over gas optimization - Prioritize security when patterns conflict

Common Combinations

Pausable + AccessControl

contract MyContract is Pausable, AccessControl {
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

    function pause() public onlyRole(PAUSER_ROLE) {
        _pause();
    }

    function unpause() public onlyRole(PAUSER_ROLE) {
        _unpause();
    }

    function criticalFunction() public whenNotPaused {
        // Function logic
    }
}

ERC20 + Ownable + Pausable

contract MyToken is ERC20, Ownable, Pausable {
    constructor() ERC20("MyToken", "MTK") Ownable(msg.sender) {}

    function pause() public onlyOwner {
        _pause();
    }

    function _update(address from, address to, uint256 value)
        internal
        override
        whenNotPaused
    {
        super._update(from, to, value);
    }
}

UUPS + AccessControl + ReentrancyGuard

contract MyUpgradeableContract is
    UUPSUpgradeable,
    AccessControlUpgradeable,
    ReentrancyGuardUpgradeable
{
    bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE");

    function _authorizeUpgrade(address newImplementation)
        internal
        override
        onlyRole(UPGRADER_ROLE)
    {}
}

Anti-Patterns to Avoid

  1. Custom access control - Use OpenZeppelin instead
  2. Manual reentrancy protection - Use ReentrancyGuard
  3. Incorrect upgrade patterns - Follow OpenZeppelin upgrade guides
  4. Mixing storage layouts - Be careful with inheritance order
  5. Skipping initialization - Always initialize upgradeable contracts
  6. Ignoring token standards - Follow ERC specifications exactly

Pattern Files

This skill provides the following pattern documentation:

  • ./patterns/upgradeable-contracts.md
    - Proxy patterns
  • ./patterns/access-control.md
    - Permission patterns
  • ./patterns/pausable.md
    - Emergency stop pattern
  • ./patterns/reentrancy-guard.md
    - Reentrancy protection
  • ./patterns/token-standards.md
    - ERC20/721/1155 standards

Example Contracts

This skill provides the following examples:

  • ./examples/ERC20-example.sol
    - Fungible token implementation
  • ./examples/ERC721-example.sol
    - NFT implementation
  • ./examples/ERC1155-example.sol
    - Multi-token implementation
  • ./examples/upgradeable-example.sol
    - UUPS upgradeable contract

Quick Reference

// Access Control
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";

// Security
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

// Tokens
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";

// Upgradeability
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

Remember: Always prefer battle-tested OpenZeppelin implementations over custom patterns. Security > Gas optimization > Code elegance.