MUD config
Certain CLI commands, such as mud tablegen
and mud worldgen
require the MUD configuration file.
This file needs to be named mud.config.ts
and be in the same folder as your foundry.toml
file.
The config is used to define:
- The tables in your project.
- The namespace(s) that
System
s and tables will be deployed in. - The
System
s in your project. By default, the deployer will find all Solidity matching*System.sol
(so any file ending inSystem.sol
, in any folder) and deploy them as publicSystem
. If you want greater control over your systems (to change their public access or their name), you can use thesystems
object in the config. - The modules that will be installed in the
World
. - The enumerations in your
World
. - Deployment and code generation options.
Multiple namespaces
Starting with version 2.1 you can put multiple namespaces in the same config file, you create a namespaces
record and within it a record for every namespace.
For example:
Sample mud.config.ts
files
A namespace
This is an extremely simple configuration file with a single namespace that contains a single table.
The System
s are defined implicitly, as all the contracts under src/namespaces/app
that match *System.sol
.
import { defineWorld } from "@latticexyz/world";
export default defineWorld({
namespaces: {
app: {
tables: {
Tasks: {
schema: {
id: "bytes32",
createdAt: "uint256",
completedAt: "uint256",
description: "string",
},
key: ["id"],
},
},
},
},
});
Source files
src/namespaces/app/systems
-System
s that belong to theapp
namespace.
Note that this is a convention, any *System.sol
under src/namespaces/<namespace>
is interpreted as a System
in that namespace.
Generated files
src/namespaces/app/codegen/tables/Tasks.sol
- the generated code forapp__Tasks
table.src/namespaces/app/codegen/index.sol
- a single file that imports all the table definitions of the namespace (in this case, onlyTasks.sol
).src/codegen/world/I*System.sol
- interfaces for all theSystem
s.src/codegen/world/IWorld.sol
- theIWorld
interface that inherits from all theI*System.sol
files.
A namespace with an explicit System
definition
By default Systems
are publicly accessible.
In this configuration, we explicitly specify TestSystem
so we can specify that access to it is limited to authorized addresses.
import { defineWorld } from "@latticexyz/world";
export default defineWorld({
namespaces: {
app: {
tables: {
Tasks: {
schema: {
id: "bytes32",
createdAt: "uint256",
completedAt: "uint256",
description: "string",
},
key: ["id"],
},
},
systems: {
TestSystem: {
openAccess: false,
},
},
},
},
});
Source files
src/namespaces/app/systems/RootSystem.sol
- TheSystem
specified inmud.config.ts
.src/namespaces/app/systems
-System
s that belong to theapp
namespace.
Note that this is a convention, any *System.sol
under src/namespaces/<namespace>
is interpreted as a System
in that namespace.
Generated files
src/namespaces/app/codegen/tables/Tasks.sol
- the generated code forapp__Tasks
.src/namespaces/app/codegen/index.sol
- a single file that imports all the table definitions (in this case, onlyTasks.sol
).src/codegen/world/I*System.sol
- interfaces for all theSystem
s, includingIRootSystem.sol
src/codegen/world/IWorld.sol
- theIWorld
interface that inherits from all theI*System.sol
files.
Two namespaces
In this example there are two namespaces, app
and config
.
Each namespace contains a single table: app__Tasks
and config__Configuration
.
import { defineWorld } from "@latticexyz/world";
export default defineWorld({
namespaces: {
app: {
tables: {
Tasks: {
schema: {
id: "bytes32",
createdAt: "uint256",
completedAt: "uint256",
description: "string",
},
key: ["id"],
},
},
},
config: {
tables: {
Configuration: {
schema: {
deployer: "address",
tokenAddress: "address",
ipAddress: "bytes4",
url: "string",
},
key: [],
},
},
},
},
});
Source files
src/namespaces/app/systems
-System
s that belong to theapp
namespace.src/namespaces/config/systems
-System
s that belong to theconfig
namespace.
Note that this is a convention, any *System.sol
under src/namespaces/<namespace>
is interpreted as a System
in that namespace.
Generated files
src/namespaces/app/codegen/tables/Tasks.sol
- the generated code forapp__Tasks
table.src/namespaces/app/codegen/index.sol
- a single file that imports all the table definitions of the namespace (in this case, onlyTasks.sol
).src/namespaces/config/systems
-System
s that belong to theconfig
namespace.src/namespaces/config/codegen/tables/Tasks.sol
- the generated code forconfig__Configuration
table.src/namespaces/config/codegen/index.sol
- a single file that imports all the table definitions of the namespace (in this case, onlyConfiguration.sol
).src/codegen/world/I*System.sol
- interfaces for all theSystem
s.src/codegen/world/IWorld.sol
- theIWorld
interface that inherits from all theI*System.sol
files.
Enumerations
import { defineWorld } from "@latticexyz/world";
export default defineWorld({
enums: {
Direction: ["Up", "Down", "Left", "Right"],
MapDirection: ["North", "East", "South", "West"],
},
namespaces: {
app: {
tables: {
Heading: {
schema: {
id: "bytes32",
direction: "Direction",
name: "string",
},
key: ["id"],
},
MapCursor: {
schema: {
id: "bytes32",
direction: "MapDirection",
name: "string",
},
key: ["id"],
},
},
},
},
});
Source files
src/namespaces/app/systems
-System
s that belong to theapp
namespace.
Note that this is a convention, any *System.sol
under src/namespaces/<namespace>
is interpreted as a System
in that namespace.
Generated files
src/namespaces/app/codegen/tables/Heading.sol
- the generated code forapp__Heading
table.src/namespaces/app/codegen/tables/MapCursor.sol
- the generated code forapp__MapCursor
table.src/namespaces/app/codegen/index.sol
- a single file that imports all the table definitions of the namespace (in this case,Heading.sol
andMapCursor.sol
).src/codegn/common.sol
- the enumerations in the config file.src/codegen/world/I*.sol
- interfaces for all theSystem
s.src/codegen/world/IWorld.sol
- theIWorld
interface that inherits from all theI*System.sol
files.
Fields within a namespace
-
tables
: a record of tables. The keys in the record are table names. The value is a record of table properties (opens in a new tab).-
schema
(record): The keys of this record are the field names in the data, which includes both the key fields and the value fields. By convention, these keys start with a lowercase letter. The values are strings that contain the data types of the fields. Note that this is the sole required field, all the others are optional. -
key
(list): A list of theschema
fields that are the key for that table. If you want a singleton table, use an empty list (as inCounter
table above). -
type
(eithertable
oroffchainTable
): The table type. The default istable
, which is a table stored onchain. If you specifyoffchainTable
, the table's data is only available offchain through events.
-
-
systems
: a record of system definitions. The keys in the record are file names without the.sol
extension. For example, if your system is namedTestSystem.sol
, useTestSystem
as the key.The value is a record of system configuration properties:
registerFunctionSelectors
(optional, defaulttrue
): abool
. Whether we want to automatically register thepublic
functions of theSystem
as function selectorsopenAccess
(optional, defaulttrue
): abool
. If set tofalse
, access is limited to:System
s in the same namespace- Addresses listed in
accessList
System
s listed inaccessList
- Addresses added to the access list after deployment.
accessList
: an array ofstring
. Each address in the array will be granted access to this system, allowing them to call it.
-
excludeSystems
: an array ofstring
: which systems to not deploy, even if their name ends with “System”.
Global configuration keys (for multi-namespace config files)
In addition to namespaces
, these fields are also supported.
-
enums
: a record of enumerations (opens in a new tab). The keys are the names of the enumerations. The values are arrays of the strings for the values the enumeration can take. -
modules
an array of module definitions: each module definition has aname
,root
(optional), andargs
key.-
name
: Name of the module to install. The same module can be installed multiple times. This should be the name of the contract file without.sol
(eg: if the file is namedDopeModule.sol
, the name of the module isDopeModule
) -
root
: whether to create aroot
module or not.root
modules have access to all tables and are not bound to namespace restrictions. -
args
: a list of arguments to be sent to theinstall
function of the module. In this array, you can use the functionresolveTableId
. This function will turn a table name from your config into its low-level ID in the World. It is useful to pass references of a table to a module.
-
-
codegen
: a record of code generation options.worldInterfaceName
astring
: The name of the interface for theWorld
. The default value isIWorld
.worldgenDirectory
astring
: The directory for system and world interfaces. The default value isworld
.
-
deploy
: a record of deployment options.-
postDeployScript
astring
: Script to execute after the deployment is complete. This script must be placed in the forge scripts directory (seefoundry.toml
) and have a.s.sol
extension. The default isPostDeploy
. -
deploysDirectory
astring
: Which folder to put the deployment artifacts into after deployment. The default is./deploys
. -
worldsFile
astring
: JSON file for the chain toWorld
deploy address mapping. The default is./worlds.json
. -
upgradeableWorldImplementation
abool
: Whether theWorld
is to be deployed behind a proxy to enable upgrades of the core World implementation. The default isfalse
.
-
Single namespace
This is an older config file format which is still supported.
import { defineWorld } from "@latticexyz/world";
export default defineWorld({
enums: {
TerrainType: ["None", "TallGrass", "Boulder"],
},
excludeSystems: ["System3", "System2"],
worldContractName: "CustomWorld",
namespace: "mud",
systems: {
IncrementSystem: {
name: "increment",
openAccess: true,
},
},
tables: {
Counter: {
schema: {
value: "uint32",
},
key: [],
},
Tasks: {
schema: {
id: "bytes32",
createdAt: "uint256",
completedAt: "uint256",
description: "string",
},
key: ["id"],
},
},
});
Global configuration keys (for single namespace config files)
The global configuration keys are all optional.
-
namespace
: astring
: which namespace to deploy the resources defined in the config into. The default value is the ROOT namespace, which is highly discouraged. -
tables
: a record of tables. The keys in the record are table names. The value is a record of table properties (opens in a new tab).-
schema
(record): The keys of this record are the field names in the data, which includes both the key fields and the value fields. By convention, these keys start with a lowercase letter. The values are strings that contain the data types of the fields. Note that this is the sole required field, all the others are optional. -
key
(list): A list of theschema
fields that are the key for that table. If you want a singleton table, use an empty list (as inCounter
table above). -
type
(eithertable
oroffchainTable
): The table type. The default istable
, which is a table stored onchain. If you specifyoffchainTable
, the table's data is only available offchain through events.
-
-
systems
: a record of system definitions. The keys in the record are file names without the.sol
extension. For example, if your system is namedTestSystem.sol
, useTestSystem
as the key.The value is a record of system configuration properties:
registerFunctionSelectors
(optional, defaulttrue
): abool
. Whether we want to automatically register thepublic
functions of theSystem
as function selectorsopenAccess
(optional, defaulttrue
): abool
. If set tofalse
, access is limited to:System
s in the same namespace- Addresses listed in
accessList
System
s listed inaccessList
- Addresses added to the access list after deployment.
accessList
: an array ofstring
. Each address in the array will be granted access to this system, allowing them to call it.
-
enums
: a record of enumerations (opens in a new tab). The keys are the names of the enumerations. The values are arrays of the strings for the values the enumeration can take. -
excludeSystems
: an array ofstring
: which systems to not deploy, even if their name ends with “System”. -
modules
an array of module definitions: each module definition has aname
,root
(optional), andargs
key.-
name
: Name of the module to install. The same module can be installed multiple times. This should be the name of the contract file without.sol
(eg: if the file is namedDopeModule.sol
, the name of the module isDopeModule
) -
root
: whether to create aroot
module or not.root
modules have access to all tables and are not bound to namespace restrictions. -
args
: a list of arguments to be sent to theinstall
function of the module. In this array, you can use the functionresolveTableId
. This function will turn a table name from your config into its low-level ID in the World. It is useful to pass references of a table to a module.
-
-
codegen
: a record of code generation options.worldInterfaceName
astring
: The name of the interface for theWorld
. The default value isIWorld
.worldgenDirectory
astring
: The directory for system and world interfaces. The default value isworld
.
-
deploy
: a record of deployment options.-
postDeployScript
astring
: Script to execute after the deployment is complete. This script must be placed in the forge scripts directory (seefoundry.toml
) and have a.s.sol
extension. The default isPostDeploy
. -
deploysDirectory
astring
: Which folder to put the deployment artifacts into after deployment. The default is./deploys
. -
worldsFile
astring
: JSON file for the chain toWorld
deploy address mapping. The default is./worlds.json
. -
upgradeableWorldImplementation
abool
: Whether theWorld
is to be deployed behind a proxy to enable upgrades of the core World implementation. The default isfalse
.
-