-
Notifications
You must be signed in to change notification settings - Fork 196
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into yonadaaa/byte-to-bits-magic-number
- Loading branch information
Showing
172 changed files
with
7,186 additions
and
469 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@latticexyz/store": patch | ||
--- | ||
|
||
Storage events are now emitted after "before" hooks, so that the resulting logs are now correctly ordered and reflect onchain logic. This resolves issues with store writes and event emissions happening in "before" hooks. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
--- | ||
"@latticexyz/cli": patch | ||
"@latticexyz/world-modules": patch | ||
"@latticexyz/world": major | ||
--- | ||
|
||
Previously `registerSystem` and `registerTable` had a side effect of registering namespaces if the system or table's namespace didn't exist yet. | ||
This caused a possible frontrunning issue, where an attacker could detect a `registerSystem`/`registerTable` transaction in the mempool, | ||
insert a `registerNamespace` transaction before it, grant themselves access to the namespace, transfer ownership of the namespace to the victim, | ||
so that the `registerSystem`/`registerTable` transactions still went through successfully. | ||
To mitigate this issue, the side effect of registering a namespace in `registerSystem` and `registerTable` has been removed. | ||
Calls to these functions now expect the respective namespace to exist and the caller to own the namespace, otherwise they revert. | ||
|
||
Changes in consuming projects are only necessary if tables or systems are registered manually. | ||
If only the MUD deployer is used to register tables and systems, no changes are necessary, as the MUD deployer has been updated accordingly. | ||
|
||
```diff | ||
+ world.registerNamespace(namespaceId); | ||
world.registerSystem(systemId, system, true); | ||
``` | ||
|
||
```diff | ||
+ world.registerNamespace(namespaceId); | ||
MyTable.register(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
"@latticexyz/store": patch | ||
--- | ||
|
||
Aligned the order of function arguments in the `Storage` library. | ||
|
||
```solidity | ||
store(uint256 storagePointer, uint256 offset, bytes memory data) | ||
store(uint256 storagePointer, uint256 offset, uint256 length, uint256 memoryPointer) | ||
load(uint256 storagePointer, uint256 offset, uint256 length) | ||
load(uint256 storagePointer, uint256 offset, uint256 length, uint256 memoryPointer) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@latticexyz/world": patch | ||
--- | ||
|
||
Namespace balances can no longer be transferred to non-existent namespaces. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
"@latticexyz/store": minor | ||
--- | ||
|
||
Improved error messages for invalid `FieldLayout`s | ||
|
||
```diff | ||
-error FieldLayoutLib_InvalidLength(uint256 length); | ||
+error FieldLayoutLib_TooManyFields(uint256 numFields, uint256 maxFields); | ||
+error FieldLayoutLib_TooManyDynamicFields(uint256 numFields, uint256 maxFields); | ||
+error FieldLayoutLib_Empty(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,9 @@ on: | |
- main | ||
pull_request: | ||
|
||
env: | ||
FOUNDRY_VERBOSITY: 5 | ||
|
||
jobs: | ||
test: | ||
name: Run tests | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,126 @@ | ||
# Config | ||
# The World config | ||
|
||
Certain CLI commands, such as [`mud tablegen`](/cli/tablegen) and [`mud worldgen`](/cli/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 in the `tables` object of your configuration. | ||
- The [namespace](/world/namespaces-access-control) the [`System`s](/world/systems) 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 in `System.sol`, in any folder) and deploy them as public `System`. | ||
If you want greater control over your systems (to change their public access or their name), you can use the `systems` object in the config. | ||
- The [modules](/world/modules) that will be installed in the `World`. | ||
|
||
The is an example of a `World` config: | ||
|
||
```tsx | ||
import { mudConfig } from "@latticexyz/world/register"; | ||
import { resolveTableId } from "@latticexyz/config"; | ||
|
||
export default mudConfig({ | ||
excludeSystems: ["System3", "System2"], | ||
worldContractName: "CustomWorld", | ||
namespace: "mud", | ||
systems: { | ||
IncrementSystem: { | ||
name: "increment", | ||
openAccess: true, | ||
}, | ||
}, | ||
tables: { | ||
CounterTable: { | ||
valueSchema: { | ||
value: "uint32", | ||
}, | ||
}, | ||
}, | ||
deploysDirectory: "./mud-deploys", | ||
modules: [ | ||
{ | ||
name: "KeysWithValueModule", | ||
root: true, | ||
args: [resolveTableId("CounterTable")], | ||
}, | ||
], | ||
}); | ||
``` | ||
|
||
## Global configuration keys | ||
|
||
The global configuration keys are all optional. | ||
|
||
- **`namespace`**: a `string`: which namespace to deploy the resources defined in the config into. | ||
The default value is the ROOT namespace. | ||
|
||
- **`excludeSystems`**: an array of `string`: which systems to not deploy, even if their name ends with “System”. | ||
|
||
- **`worldContractName`**: a `string`: the name of a contract in your project implementing the `IWorld` interface. | ||
Useful if you want to modify the default World implementation, but potentially dangerous. | ||
- **`deploysDirectory`** a `string`: which folder to put the deployment artifacts into after deployment. | ||
|
||
- **`modules`** an array of module definitions: each module definition has a `name`, `root` (optional), and `args` 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 named `DopeModule.sol`, the name of the module is `DopeModule`) | ||
|
||
- `root`: whether to create a `root` 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 the `install` function of the module. In this array, you can use the function `resolveTableId`. 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. | ||
|
||
- **`systems`**: a record of system definitions. The keys in the record are file names without the `.sol` extension. For example, if your system is named `TestSystem.sol`, use `TestSystem` as the key. | ||
|
||
The value is a record of system configuration properties: | ||
|
||
- `fileSelector` (optional): a `string`: the file selector for the system. | ||
- `openAccess` (optional, default `true`): a `bool`: if set to `false`, only the systems in the same namespace and the addresses or systems listed in the the `accessList` array have access. | ||
|
||
- `accessList` (required if openAccess is `false`): an array of `string`. Each address in the array will be granted access to this system, allowing them to call it. | ||
|
||
- **`tables`**: a record of tables. The keys in the record are table names. | ||
The value is a record of [table properties](https://github.com/latticexyz/mud/blob/main/packages/store/ts/config/storeConfig.ts#L110-L135). | ||
|
||
- **`valueSchema`** (record): | ||
The keys of this record are the field names of the value (which should 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. | ||
|
||
- **`keySchema`** (record): | ||
The keys of this record are the field names of the key (which should start with a lowercase letter). | ||
The values are strings that contain the data types of the fields. | ||
|
||
The default value is: | ||
|
||
```json | ||
{ "key": "bytes32" } | ||
``` | ||
|
||
For a singleton table (one that contains a single row), use `{}` as the key schema. | ||
|
||
- **`directory`** (string): | ||
Directory in which to create the table. | ||
The default is `tables`, so by default tables are created in `src/codegen/tables`. | ||
|
||
- **`tableIdArgument`** (bool): | ||
Make methods accept `tableId` argument instead of it being a hardcoded constant. | ||
The default is `false` because you can achieve the same result using [`StoreSwitch`](/store/table-libraries#storeswitch). | ||
|
||
- **`storeArgument`** (bool): | ||
Include methods that accept a manual `IStore` argument. | ||
The default is `true`. | ||
|
||
- **`offchainOnly`**: (bool): | ||
Table's information is available offchain (using [events](https://docs.soliditylang.org/en/latest/contracts.html#events)), but don't store in onchain. | ||
These tables require a lot less gas. | ||
|
||
- **`dataStruct`**: (bool): | ||
Include a [data struct](https://docs.soliditylang.org/en/v0.8.23/types.html#structs) and methods for it. | ||
Default is false for 1-column tables; true for multi-column tables. | ||
|
||
Sample code for using a table library with `dataStruct`: | ||
|
||
```solidity | ||
// no data struct | ||
MyTable.set(keccak256("some.key"), 1, 12, "foo"); | ||
// data struct | ||
MyTable.set(keccak256("some.key"), { field1: 1, field2: 12, stringField: "foo" }); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,115 @@ | ||
# mud test | ||
|
||
**Coming soon** | ||
This command runs the tests in a MUD project. Internally, it runs the following steps: | ||
|
||
1. Starts an [`anvil`](https://book.getfoundry.sh/reference/anvil/) instance. | ||
{/* This could be either an empty blockchain, or one that can be forked for a [fork test](https://book.getfoundry.sh/forge/fork-testing). */} | ||
1. Deploys the `World` and all related `System`s using [`mud deploy`](./deploy). | ||
1. Runs tests using [`forge test`](https://book.getfoundry.sh/forge/tests) and passes the deployed world address to the tests via the `WORLD_ADDRESS` environment variable. | ||
|
||
## Command line options | ||
|
||
| Option | Meaning | Type | Default value | | ||
| ----------------------- | ---------------------------------------------- | ------- | ---------------------------------------------------------- | | ||
| `--version` | Show version number | boolean | `false` | | ||
| `--configPath` | Path to the config file | string | `mud.config.ts` | | ||
| `--printConfig` | Print the resolved config | boolean | `false` | | ||
| `--saveDeployment` | Save the deployment info to a file | boolean | `true` | | ||
| `--profile` | The foundry profile to use | string | `local` | | ||
| `--srcDir` | Source directory | string | Foundry `src` directory | | ||
| `--skipBuild` | Skip rebuilding the contracts before deploying | boolean | `false` | | ||
| `--alwaysRunPostDeploy` | Run `PostDeploy.s.sol` after each deploy | boolean | `false` (run the script only when deploying a new `World`) | | ||
| `--port` | Port for the testing `anvil` instance | number | 4242 | | ||
| `--help` | Show help | boolean | `false` | | ||
|
||
## Examples | ||
|
||
```sh copy | ||
pnpm mud test | ||
``` | ||
|
||
## Writing MUD tests | ||
|
||
MUD test contracts inherit from [`MudTest`](https://github.com/latticexyz/mud/blob/main/packages/world/test/MudTest.t.sol). | ||
This contract gets the `World` address from the `$WORLD_ADDRESS` environment variable and sets it as the `Store` address. | ||
|
||
<details> | ||
|
||
<summary>Line by line explanation of a test</summary> | ||
|
||
This is an explanation of [the test](https://github.com/latticexyz/mud/blob/main/templates/react/packages/contracts/test/TasksTest.t.sol) for the [React template](https://github.com/latticexyz/mud/tree/main/templates/react) contracts. | ||
|
||
```solidity | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.21; | ||
import "forge-std/Test.sol"; | ||
import { MudTest } from "@latticexyz/world/test/MudTest.t.sol"; | ||
``` | ||
|
||
Import the general definitions required in all MUD tests. | ||
|
||
```solidity | ||
import { IWorld } from "../src/codegen/world/IWorld.sol"; | ||
import { Tasks, TasksData } from "../src/codegen/index.sol"; | ||
``` | ||
|
||
Import the definitions required for this test, the `World` we can access and the tables we'll use. | ||
|
||
```solidity | ||
contract TasksTest is MudTest { | ||
function testWorldExists() public { | ||
``` | ||
|
||
MUD tests are [Foundry tests](https://book.getfoundry.sh/forge/tests). | ||
Any public function that starts with `test` is a test that gets executed. | ||
|
||
```solidity | ||
uint256 codeSize; | ||
address addr = worldAddress; | ||
``` | ||
|
||
The `World` address comes from the [`MudTest`](https://github.com/latticexyz/mud/blob/main/packages/world/test/MudTest.t.sol#L11). | ||
|
||
```solidity | ||
assembly { | ||
codeSize := extcodesize(addr) | ||
} | ||
assertTrue(codeSize > 0); | ||
} | ||
``` | ||
|
||
Use [`extcodesize`](https://www.evm.codes/#3b?fork=shanghai) to get the size of the `World` contract. | ||
If the deploy process failed, there wouldn't be any code there. | ||
|
||
```solidity | ||
function testTasks() public { | ||
// Expect task to exist that we created during PostDeploy script | ||
TasksData memory task = Tasks.get("1"); | ||
``` | ||
|
||
Use the structure for a table entry's values that is created as part of code generation. | ||
|
||
```solidity | ||
assertEq(task.description, "Walk the dog"); | ||
assertEq(task.completedAt, 0); | ||
``` | ||
|
||
Verify the information that is prepopulated by [the `PostDeploy.s.sol` script](https://github.com/latticexyz/mud/blob/main/templates/react/packages/contracts/script/PostDeploy.s.sol). | ||
|
||
```solidity | ||
// Expect the task to be completed after calling completeTask from our TasksSystem | ||
IWorld(worldAddress).completeTask("1"); | ||
``` | ||
|
||
Call a `System` to modify the table data. | ||
|
||
```solidity | ||
assertEq(Tasks.getCompletedAt("1"), block.timestamp); | ||
} | ||
} | ||
``` | ||
|
||
Verify that the call changed the data correctly. | ||
|
||
</details> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.