Exploring ECS in Solidity with MUD Framework

This article delves into realizing the Entity Component System (ECS) using Solidity, specifically through the lens of the MUD framework developed by Lattice.

MUD, an advanced Solidity framework, incorporates the ECS, offering a novel approach to contract design. Familiarity with the Diamond Proxy Pattern (EIP2535) is beneficial, as MUD partially mirrors this pattern. MUD Framework | Diamond Proxy Pattern

What is the ECS?

Originating from video game development, the ECS is a software architecture paradigm focusing on composition over inheritance. It counters the complexity of deep inheritance chains in Solidity contracts, promoting modular design through separate components and logic.

  • Entity: Essentially an ID representing an object.

  • Component: Structured data, akin to a database table.

  • System: Houses the logic.

Applying ECS in MUD

Focusing on the Store function within MUD, we see how ECS manifests:

1. Configuring the Layout: Define the table layout in mud.config, specifying entities and component structures.

Position: {
  valueSchema: {
    x: "uint32",
    y: "uint32",
  },
  ...

2. Creating Entities and Components: Utilize MUD's CLI to generate Entity IDs and Components based on mud.config.

//Auto-generated
//Entity ID
bytes32 constant _tableId = bytes32(abi.encodePacked(bytes16(""), bytes16("Position")));
bytes32 constant PositionTableId = _tableId;

//Component
struct PositionData {
  uint32 x;
  uint32 y;
}

library Position {
  function getX() internal view returns (uint32 x) {
...

Note that Position is a Library, not a contract, comprising an Entity ID, struct for columns, and internal getter/setter.

3. Dveloping System Contracts: System contracts interact with and control table data.

//set data on Position table
import { PositionTable } from "../codegen/index.sol";

contract PositionSystem is System {
  function move(uint32 x, uint32 y) public {
    PositionTable.set(x, y);
  }
}

Users interact with the system's functions to perform operations.

In practice, users transact with the World contract, which uses delegateCall to interact with System contracts. This ensures data is stored within the World contract's storage space, preventing storage conflicts.

MUD's Architecture Overview
MUD's Architecture Overview

Comparing MUD and Diamond Proxy

MUD and Diamond Proxy Pattern are similar in several respects.

Diamond Proxy Pattern
Diamond Proxy Pattern

While MUD and Diamond Proxy share similarities in their use of delegateCall and storage separation, their objectives differ. Diamond Proxy focuses on upgradeability, whereas MUD implements the ECS for structuring contracts, particularly beneficial in complex applications like games.

However, MUD consists of a large number of contracts compared to Diamond Proxy, indicating that it is a very complex framework.

Considering MUD's complexity, there's a potential for developing a new, lighter framework that maintains the ECS but simplifies the structure. Such a framework could consist of auto-generated component contracts and a streamlined store contract.

Conclusion and Invitation for Collaboration

The MUD framework offers a unique approach to implementing the ECS in Solidity. However, its complexity prompts the question of whether a simpler, more lightweight framework could be equally effective. I invite fellow engineers to explore this possibility further. For thoughts, collaborations, or discussions, please feel free to reach out.

  • Github repository (under construction)
  • X
Subscribe to yamapyblack
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.