Modular Smart Contract Architecture
ChainSocial’s smart contracts are built to evolve. New features ship without downtime, without migrations, and without risking existing user data. This page explains how and why that works.
The Problem with Traditional Smart Contracts
Most smart contracts are immutable by default. Once deployed, they cannot be changed. This creates a painful set of tradeoffs:
| Approach | Tradeoff |
|---|---|
| Immutable contracts | Cannot fix bugs or add features. Requires deploying an entirely new contract and migrating all data. |
| Proxy pattern (ERC-1967) | Introduces storage collision risks. A single slot misalignment can corrupt all contract state. Upgrade logic is complex and error-prone. |
| Diamond pattern (ERC-2535) | Reduces collision risk but adds significant complexity. Facet management, selector clashes, and storage layout coordination become ongoing burdens. |
| Migrate and redirect | Users must move their data to a new contract. Breaks integrations, loses history, fragments the ecosystem. |
All of these approaches share a fundamental problem: they treat storage and logic as tightly coupled. Changing the logic means risking the data.
How MUD Solves This
ChainSocial uses MUD , a framework that cleanly separates data from logic at the protocol level.
The World Contract
At the center of ChainSocial is a single World contract deployed at 0x7405fCbEc24C00278b7e821Ace222f5CFfa6c6eA on Base mainnet.
The World is a permanent kernel. It was deployed once and will live forever. It serves three roles:
- Router — All external calls go through the World, which routes them to the appropriate system
- Storage layer — All data (profiles, posts, follows, messages) lives in the World’s storage, organized into typed tables
- Access controller — Fine-grained permissions determine which systems can read and write which tables
The World itself contains no application logic. It is pure infrastructure.
Systems Are Modular Plugins
Application logic lives in Systems — stateless contracts that the World delegates calls to. Each system is a self-contained module:
┌─────────────────────────────────────────────────────────────────┐
│ World Contract │
│ (Permanent, deployed once) │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Tables (Data Layer) │ │
│ │ Profile, Post, Content, Follow, Reaction, Block, │ │
│ │ DirectMessage, Delegation, Notification, Plugin... │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ProfileSystem │ │ PostSystem │ │FollowSystem │ Current │
│ └──────────────┘ └──────────────┘ └──────────────┘ Systems │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ContentSystem │ │ReactionSys │ │ BlockSystem │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │DirectMsgSys │ │DelegationSys │ │ PluginSystem │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ TippingSys │ │ CuratorSys │ Future systems -- added │
│ │ (future) │ │ (future) │ without touching existing │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘Systems are deployed as separate contracts and registered with the World. They execute via delegatecall, meaning they read and write directly to the World’s storage. This is why systems are stateless — they have no storage of their own.
What “Modular” Actually Means
When we say ChainSocial’s contracts are modular, we mean these specific operations are possible at any time:
Add a new system. Deploy a new contract, register it with the World, and grant it access to the tables it needs. All existing systems continue to work. All existing data remains intact. Users do not need to do anything.
Upgrade an existing system. Deploy a new version of a system contract and replace the old registration. The new system reads and writes the same tables as the old one. No data migration is needed because the data never moved.
Remove a system. Deregister a system from the World. Its logic is no longer callable, but the data it created remains in the World’s tables for other systems to use.
Add new tables. Define new table schemas and register them with the World. Existing tables are unaffected.
None of these operations require redeploying the World contract. None of them affect existing data. None of them cause downtime.
Why This Matters
For Users
Your data is permanent. Profiles, posts, followers, messages — all of it lives in the World contract’s storage, not in any individual system. When ChainSocial adds new features or fixes bugs, your existing content is never at risk.
No migrations, ever. You will never be asked to “migrate your account” to a new version of ChainSocial. The World at 0x7405fCbEc24C00278b7e821Ace222f5CFfa6c6eA is the permanent home of all ChainSocial state.
The platform evolves without disruption. New capabilities appear as new systems are registered. Your experience improves without you needing to take any action.
For Developers
Ship features without risk. Adding a new system cannot break existing systems. The separation between data and logic means a bug in a new tipping system cannot corrupt the profile table. Each system operates within its granted permissions.
No storage collision anxiety. Unlike proxy patterns, MUD tables have explicit schemas with named fields. There is no raw storage slot math. A new system that writes to the Post table uses the same schema-based access as the original PostSystem.
Incremental development. Build and deploy one system at a time. The Curator system, for example, can be developed and deployed independently — it reads from existing Post and Profile tables and writes to its own new tables.
For the Ecosystem
Third-party extensibility. Anyone can build and deploy systems that interact with ChainSocial data. A developer could create a tipping system, a reputation score system, or an analytics system — all plugging into the same World contract with the same data.
Composable by default. Systems can call each other through the World interface. A new “boost post” system could call the existing PostSystem to verify a post exists, then write to its own Boost table. Cross-system composition is a first-class pattern.
Namespaced isolation. MUD’s namespace system means different protocols can coexist in the same World without conflicts. ChainSocial operates under the chainsocial namespace, leaving room for other namespaces to be added.
A Concrete Example: Adding AI Curation
ChainSocial’s AI Curator system demonstrates this architecture in practice. Here is how a new feature gets added without touching existing contracts:
Step 1: Define new tables for curator-specific data (curation scores, source tracking, evaluation metadata). These tables are registered with the World alongside existing tables.
Step 2: Deploy the CuratorSystem as a new contract. It reads from existing tables (Post, Profile, Content) to understand what has been posted and by whom.
Step 3: Grant access. The CuratorSystem gets read access to existing tables and write access to its own new tables.
Step 4: Done. The curator can now evaluate posts, assign scores, and track sources — all without modifying ProfileSystem, PostSystem, or any other existing contract.
If the CuratorSystem needs to be updated (for example, to improve its scoring algorithm), a new version is deployed and registered. The old version is replaced. The data in the curator tables persists.
Comparison with Traditional Approaches
| Capability | Proxy Pattern | Diamond Pattern | MUD World |
|---|---|---|---|
| Add new logic | Requires careful storage layout management | Possible but requires facet coordination | Register a new system. No coordination needed. |
| Storage safety | Manual slot management. Collisions corrupt state. | Better isolation but still requires discipline | Schema-based tables. No raw slot access. |
| Data persistence during upgrade | Data persists but storage layout must match exactly | Data persists with careful management | Data always persists. Systems are stateless. |
| Multi-feature composition | Single implementation contract | Multiple facets, selector management | Independent systems, cross-system calls via World |
| Third-party extensions | Not practical | Complex coordination required | Deploy a system, request table access |
| Rollback capability | Redeploy old implementation | Swap facets back | Re-register old system contract |
Technical Details
How System Registration Works
Systems are registered with a resource ID that encodes the namespace and system name:
// Resource ID format: namespace + system name
// ChainSocial systems live under the "chainsocial" namespace
bytes32 resourceId = ResourceId.encode("chainsocial", "ProfileSystem");The World maintains a mapping from resource IDs to system contract addresses. When a call comes in, the World looks up the target system and executes it via delegatecall.
Access Control
Each system is granted explicit permissions on a per-table basis:
- Write access — The system can create, update, and delete records in the table
- Read access — All systems can read all tables (reads are free and permissionless)
This means a TippingSystem can read from the Post table to verify a post exists, but it cannot modify post records unless explicitly granted write access.
The Namespace Owner
Each namespace has an owner (typically the deployer). The namespace owner can:
- Register and deregister systems
- Grant and revoke table access
- Transfer namespace ownership
For ChainSocial, the namespace owner is the protocol team. Future governance mechanisms could transfer ownership to a DAO or multisig.
Upgradeable World Implementation
ChainSocial’s MUD configuration includes upgradeableWorldImplementation: true, which means even the World contract’s core routing logic can be upgraded if needed. This is a safety valve for critical infrastructure fixes, not a routine operation.
Current Systems
ChainSocial currently has these systems registered with the World:
| System | Purpose | Tables Written |
|---|---|---|
ProfileSystem | User identity and metadata | Profile, ProfileField |
UsernameSystem | Username claiming and fees | UsernameRegistry, UsernameConfig |
ContentSystem | Content storage (inline, IPFS, URL) | Content |
PostCore | Post creation and management | Post, PostStats, PostByAuthor |
PostInlineSystem | Inline post creation | Post, Content, PostStats |
PostBatchSystem | Batch post operations | Post, Content, PostStats |
PostFeeSystem | Post fee configuration | PostFeeConfig |
FollowSystem | Follow/unfollow with batch support | Follow, FollowStats |
ReactionSystem | Post reactions (likes, etc.) | Reaction, PostStats |
BlockSystem | User blocking | Block |
DirectMessageSystem | Direct messaging | DirectMessage, Conversation |
DelegationSystem | Permission delegation | Delegation |
NotificationSystem | Activity notifications | Notification |
ModerationSystem | Content reporting and moderation | Report, HiddenContent |
IndexSystem | Post and hashtag indexing | PostByAuthor, PostByHashtag, Hashtag |
VersionSystem | Protocol versioning | ProtocolVersion |
PluginRegistrySystem | Plugin registration | PluginMetadata |
PluginInstallSystem | Plugin installation | UserPluginInstalls |
PluginAdminSystem | Plugin administration | PluginPermissions, PluginHooks |
Each of these can be independently upgraded. New systems can be added to this list at any time.
Next Steps
- Core Systems — Detailed documentation for each system
- Plugins — Build third-party extensions
- Smart Contracts Overview — Architecture overview and calling conventions