Diamond Pattern

CapSign uses the Diamond Pattern for all smart contracts. This guide explains why and how.

What is the Diamond Pattern?

The Diamond Pattern (EIP-2535) is a modular smart contract architecture that:

  • Splits functionality into separate contracts called facets

  • Uses a single proxy contract called a diamond

  • Delegates calls to the appropriate facet

  • Allows unlimited contract size

  • Enables upgrades without changing the address

Why Use Diamonds?

1. No Size Limit

Standard contracts have a 24KB limit. Diamonds have no limit.

Example:

  • Token contract needs: ERC-20, lots, compliance, admin, metadata

  • Total: ~40KB

  • Solution: Split into 5 facets, each <24KB

2. Upgradeability

Add, replace, or remove features without redeploying:

3. Gas Efficiency

Facets deployed once, reused across all diamonds:

  • Deploy TokenERC20Facet once

  • Every token diamond uses the same facet

  • ~90% gas savings on deployment

4. Modularity

Features organized logically:

  • TokenERC20Facet - ERC-20 functions

  • TokenLotsFacet - Lot management

  • TokenAdminFacet - Admin functions

Easy to understand and maintain.

Diamond Architecture

Components

Diamond (Proxy):

  • Single address

  • Delegates to facets

  • Stores facet addresses

  • Manages upgrades

Facets (Implementation):

  • Contain actual logic

  • Reusable across diamonds

  • No storage (use diamond storage)

Diamond Storage:

  • State stored in diamond

  • Each facet has unique storage slot

  • No storage collisions

Call Flow

  1. User calls function on diamond

  2. Diamond looks up which facet handles it

  3. Diamond delegates to facet

  4. Facet executes using diamond's storage

  5. Result returned to user

CapSign Diamonds

Wallet Diamond

Token Diamond

Offering Diamond

Diamond Storage

Why Diamond Storage?

Standard Solidity storage causes collisions when facets share a diamond.

Solution: Each facet uses a unique storage slot.

Implementation

Usage in Facets

Upgrading Diamonds

DiamondCut

Add, replace, or remove facets:

Example: Adding Feature

Best Practices

Facet Design

  • Single responsibility - Each facet does one thing

  • No storage - Use diamond storage

  • Internal functions - Use base contracts for shared logic

  • Events - Emit events for state changes

Security

  • Access control - Protect sensitive functions

  • Reentrancy guards - Prevent reentrancy attacks

  • Pause mechanisms - Emergency stop functionality

  • Upgrade safeguards - Require multi-sig for upgrades

Gas Optimization

  • Singleton facets - Deploy facets once, reuse everywhere

  • Efficient selectors - Group related functions in same facet

  • Minimal delegatecalls - Keep call paths short

Limitations

Selector Conflicts

Each function selector must be unique across all facets:

Complexity

Diamonds are more complex than standard contracts:

  • More files to manage

  • Deployment more involved

  • Testing requires more setup

Worth it for large, upgradeable systems.

Resources

See Also

  • Wallets - Wallet diamond architecture

  • Tokens - Token diamond architecture

  • Offerings - Offering diamond architecture

Last updated

Was this helpful?