How MUD models data
The MUD framework helps you to model your onchain state in a way that enables building applications with familiar tooling, like relational databases.
In your MUD config, you define data as a set of tables. Like relational databases, these tables have “columns” by way of two MUD concepts: a key schema and a value schema. Each one has a set of fields that map to Solidity types.
Defining tables
Let's say we're making a game where players can move around a map. The definition for a Position
table might look something like:
export default mudConfig({
tables: {
Position: {
keySchema: {
player: "address",
},
valueSchema: {
x: "int32",
y: "int32",
},
},
},
});
Translating the table definition above would look like this in a relational database:
player | x | y |
---|---|---|
0x1234 | -5 | 1 |
0x5678 | 3 | 6 |
Because player
in part of the key schema, we would have a unique/primary key constraint on player
.
Let's add another table for terrain at a given position on the map. MUD allows for multiple keys in the key schema and, like databases, we call these composite keys.
export default mudConfig({
tables: {
Position: {
keySchema: {
player: "address",
},
valueSchema: {
x: "int32",
y: "int32",
},
},
Terrain: {
keySchema: {
x: "int32",
y: "int32",
},
valueSchema: {
terrainType: "string",
},
},
},
});
Similarly, the relational database representation of that table would look like:
x | y | terrainType |
---|---|---|
-1 | 0 | grass |
0 | 1 | tree |
1 | 0 | grass |
Because we have a composite key of x
and y
, we would have a unique/primary key constraint on the tuple of (x, y)
.
Tables on chain
Solidity and the EVM have much more limited data structures, so how can we express a relational database onchain? MUD takes the concept of tables and does a few things with them:
- encodes each table record as a key/value pair before storing onchain
- emits an event for each mutation
- provides a typed Solidity libraries to abstract this away
Field types
Key schema fields can use all of Solidity's static-length primitive types like uint256
, address
, bool
.
Value schema fields can use all of Solidity's static-length primitive types, arrays of those static-length primitive types, as well as and string
and bytes
.
Enums and user types are also supported and automatically map down to their Solidity primitive types.
More complex types like structs, string[]
, and bytes[]
are not yet supported. We'll cover the reasons why in our encoding/decoding guide.