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
TokenERC20FacetonceEvery token diamond uses the same facet
~90% gas savings on deployment
4. Modularity
Features organized logically:
TokenERC20Facet- ERC-20 functionsTokenLotsFacet- Lot managementTokenAdminFacet- 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
User calls function on diamond
Diamond looks up which facet handles it
Diamond delegates to facet
Facet executes using diamond's storage
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
Last updated
Was this helpful?