From 0c43567431e8c485160e0d01d8b212ab3e02ef76 Mon Sep 17 00:00:00 2001 From: vdrg Date: Tue, 1 Apr 2025 12:09:00 -0300 Subject: [PATCH 01/10] Support systems without suffix by adding them to MUD config --- packages/world/ts/node/getSystemContracts.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/world/ts/node/getSystemContracts.ts b/packages/world/ts/node/getSystemContracts.ts index 76aff24a4d..60e4313c53 100644 --- a/packages/world/ts/node/getSystemContracts.ts +++ b/packages/world/ts/node/getSystemContracts.ts @@ -22,10 +22,22 @@ export async function getSystemContracts({ pattern: path.join(config.sourceDirectory, "**"), }); + // Get systems from the top-level systems object + const topLevelSystems = Object.keys(config.systems); + + // Get systems from namespaces + const namespaceSystems = Object.values(config.namespaces || {}).flatMap((namespace) => + Object.keys(namespace.systems || {}), + ); + + // Combine both sets of systems + const configSystems = [...topLevelSystems, ...namespaceSystems]; + return solidityFiles .filter( (file) => - file.basename.endsWith("System") && + // Include files with the System suffix and files defined in config + (file.basename.endsWith("System") || configSystems.includes(file.basename)) && // exclude the base System contract file.basename !== "System" && // exclude interfaces From 31ae7d61a31b1517b0622fe16e4078ae18f9073a Mon Sep 17 00:00:00 2001 From: V Date: Tue, 1 Apr 2025 12:14:24 -0300 Subject: [PATCH 02/10] Create small-horses-own.md --- .changeset/small-horses-own.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/small-horses-own.md diff --git a/.changeset/small-horses-own.md b/.changeset/small-horses-own.md new file mode 100644 index 0000000000..5a9755239c --- /dev/null +++ b/.changeset/small-horses-own.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/world": patch +--- + +Support systems without the System suffix by adding them to the MUD config. From ab0ad912cb159b4dab35b6414556bcbf8bd78b87 Mon Sep 17 00:00:00 2001 From: vdrg Date: Tue, 1 Apr 2025 13:18:15 -0300 Subject: [PATCH 03/10] Use system labels from namespaces config --- packages/world/ts/node/getSystemContracts.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/world/ts/node/getSystemContracts.ts b/packages/world/ts/node/getSystemContracts.ts index 60e4313c53..c7f17a11cf 100644 --- a/packages/world/ts/node/getSystemContracts.ts +++ b/packages/world/ts/node/getSystemContracts.ts @@ -22,22 +22,16 @@ export async function getSystemContracts({ pattern: path.join(config.sourceDirectory, "**"), }); - // Get systems from the top-level systems object - const topLevelSystems = Object.keys(config.systems); - - // Get systems from namespaces - const namespaceSystems = Object.values(config.namespaces || {}).flatMap((namespace) => - Object.keys(namespace.systems || {}), + // Get system labels from all namespaces + const configSystemLabels = Object.values(config.namespaces || {}).flatMap((namespace) => + Object.values(namespace.systems).map((system) => system.label), ); - // Combine both sets of systems - const configSystems = [...topLevelSystems, ...namespaceSystems]; - return solidityFiles .filter( (file) => // Include files with the System suffix and files defined in config - (file.basename.endsWith("System") || configSystems.includes(file.basename)) && + (file.basename.endsWith("System") || configSystemLabels.includes(file.basename)) && // exclude the base System contract file.basename !== "System" && // exclude interfaces From d85b80c2aa717a89f915a198c2cb6ad4c3e1009d Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Tue, 8 Apr 2025 11:32:03 +0100 Subject: [PATCH 04/10] parse system source --- packages/cli/src/build.ts | 3 +- .../src/codegen/utils/contractToInterface.ts | 70 +++---------------- .../src/codegen/utils/findContractNode.ts | 16 +++++ .../src/codegen/utils/findSymbolImport.ts | 40 +++++++++++ packages/common/src/codegen/utils/index.ts | 1 + .../common/src/codegen/utils/parseSystem.ts | 40 +++++++++++ .../ts/build.ts | 4 +- packages/world-module-metadata/ts/build.ts | 4 +- .../test/StandardDelegationsModule.t.sol | 2 +- packages/world/src/System.sol | 2 +- packages/world/test/World.t.sol | 14 ++-- packages/world/ts/node/getSystemContracts.ts | 35 +++++----- packages/world/ts/scripts/build.ts | 12 ++-- 13 files changed, 146 insertions(+), 97 deletions(-) create mode 100644 packages/common/src/codegen/utils/findContractNode.ts create mode 100644 packages/common/src/codegen/utils/findSymbolImport.ts create mode 100644 packages/common/src/codegen/utils/parseSystem.ts diff --git a/packages/cli/src/build.ts b/packages/cli/src/build.ts index 325e11ed56..4561606350 100644 --- a/packages/cli/src/build.ts +++ b/packages/cli/src/build.ts @@ -16,7 +16,8 @@ type BuildOptions = { }; export async function build({ rootDir, config, foundryProfile }: BuildOptions): Promise { - await Promise.all([tablegen({ rootDir, config }), worldgen({ rootDir, config })]); + await tablegen({ rootDir, config }); + await worldgen({ rootDir, config }); await printCommand( execa("forge", ["build"], { stdio: "inherit", diff --git a/packages/common/src/codegen/utils/contractToInterface.ts b/packages/common/src/codegen/utils/contractToInterface.ts index a896404fac..914860b188 100644 --- a/packages/common/src/codegen/utils/contractToInterface.ts +++ b/packages/common/src/codegen/utils/contractToInterface.ts @@ -1,11 +1,8 @@ import { parse, visit } from "@solidity-parser/parser"; -import type { - ContractDefinition, - SourceUnit, - TypeName, - VariableDeclaration, -} from "@solidity-parser/parser/dist/src/ast-types"; +import type { SourceUnit, TypeName, VariableDeclaration } from "@solidity-parser/parser/dist/src/ast-types"; import { MUDError } from "../../errors"; +import { findContractNode } from "./findContractNode"; +import { SymbolImport, findSymbolImport } from "./findSymbolImport"; export interface ContractInterfaceFunction { name: string; @@ -19,11 +16,6 @@ export interface ContractInterfaceError { parameters: string[]; } -interface SymbolImport { - symbol: string; - path: string; -} - /** * Parse the contract data to get the functions necessary to generate an interface, * and symbols to import from the original contract. @@ -106,20 +98,6 @@ export function contractToInterface( }; } -export function findContractNode(ast: SourceUnit, contractName: string): ContractDefinition | undefined { - let contract: ContractDefinition | undefined = undefined; - - visit(ast, { - ContractDefinition(node) { - if (node.name === contractName) { - contract = node; - } - }, - }); - - return contract; -} - function parseParameter({ name, typeName, storageLocation }: VariableDeclaration): string { let typedNameWithLocation = ""; @@ -197,42 +175,10 @@ function typeNameToSymbols(typeName: TypeName | null): string[] { } } -// Get imports for given symbols. -// To avoid circular dependencies of interfaces on their implementations, -// symbols used for args/returns must always be imported from an auxiliary file. -// To avoid parsing the entire project to build dependencies, -// symbols must be imported with an explicit `import { symbol } from ...` function symbolsToImports(ast: SourceUnit, symbols: string[]): SymbolImport[] { - const imports: SymbolImport[] = []; - - for (const symbol of symbols) { - let symbolImport: SymbolImport | undefined; - - visit(ast, { - ImportDirective({ path, symbolAliases }) { - if (symbolAliases) { - for (const symbolAndAlias of symbolAliases) { - // either check the alias, or the original symbol if there's no alias - const symbolAlias = symbolAndAlias[1] || symbolAndAlias[0]; - if (symbol === symbolAlias) { - symbolImport = { - // always use the original symbol for interface imports - symbol: symbolAndAlias[0], - path, - }; - return; - } - } - } - }, - }); - - if (symbolImport) { - imports.push(symbolImport); - } else { - throw new MUDError(`Symbol "${symbol}" has no explicit import`); - } - } - - return imports; + return symbols.map((symbol) => { + const symbolImport = findSymbolImport(ast, symbol); + if (!symbolImport) throw new MUDError(`Symbol "${symbol}" has no explicit import`); + return symbolImport; + }); } diff --git a/packages/common/src/codegen/utils/findContractNode.ts b/packages/common/src/codegen/utils/findContractNode.ts new file mode 100644 index 0000000000..cccc8822f0 --- /dev/null +++ b/packages/common/src/codegen/utils/findContractNode.ts @@ -0,0 +1,16 @@ +import { visit } from "@solidity-parser/parser"; +import type { ContractDefinition, SourceUnit } from "@solidity-parser/parser/dist/src/ast-types"; + +export function findContractNode(ast: SourceUnit, contractName: string): ContractDefinition | undefined { + let contract: ContractDefinition | undefined = undefined; + + visit(ast, { + ContractDefinition(node) { + if (node.name === contractName) { + contract = node; + } + }, + }); + + return contract; +} diff --git a/packages/common/src/codegen/utils/findSymbolImport.ts b/packages/common/src/codegen/utils/findSymbolImport.ts new file mode 100644 index 0000000000..2b3d5ac9b1 --- /dev/null +++ b/packages/common/src/codegen/utils/findSymbolImport.ts @@ -0,0 +1,40 @@ +import { visit } from "@solidity-parser/parser"; +import type { SourceUnit } from "@solidity-parser/parser/dist/src/ast-types"; + +export interface SymbolImport { + symbol: string; + path: string; +} + +/** + * Get import for given symbol. + * + * To avoid circular dependencies of interfaces on their implementations, + * symbols used for args/returns must always be imported from an auxiliary file. + * To avoid parsing the entire project to build dependencies, + * symbols must be imported with an explicit `import { symbol } from ...` + */ +export function findSymbolImport(ast: SourceUnit, symbol: string): SymbolImport | undefined { + let symbolImport: SymbolImport | undefined; + + visit(ast, { + ImportDirective({ path, symbolAliases }) { + if (symbolAliases) { + for (const symbolAndAlias of symbolAliases) { + // either check the alias, or the original symbol if there's no alias + const symbolAlias = symbolAndAlias[1] ?? symbolAndAlias[0]; + if (symbol === symbolAlias) { + symbolImport = { + // always use the original symbol for interface imports + symbol: symbolAndAlias[0], + path, + }; + return; + } + } + } + }, + }); + + return symbolImport; +} diff --git a/packages/common/src/codegen/utils/index.ts b/packages/common/src/codegen/utils/index.ts index b037143393..2e80179c69 100644 --- a/packages/common/src/codegen/utils/index.ts +++ b/packages/common/src/codegen/utils/index.ts @@ -1,3 +1,4 @@ export * from "./contractToInterface"; export * from "./format"; export * from "./formatAndWrite"; +export * from "./parseSystem"; diff --git a/packages/common/src/codegen/utils/parseSystem.ts b/packages/common/src/codegen/utils/parseSystem.ts new file mode 100644 index 0000000000..e908b3708a --- /dev/null +++ b/packages/common/src/codegen/utils/parseSystem.ts @@ -0,0 +1,40 @@ +import { parse, visit } from "@solidity-parser/parser"; + +import { findContractNode } from "./findContractNode"; +import { findSymbolImport } from "./findSymbolImport"; + +const baseSystemName = "System"; +const baseSystemPath = "@latticexyz/world/src/System.sol"; + +export function parseSystem( + source: string, + contractName: string, +): undefined | { contractType: "contract" | "abstract" } { + const ast = parse(source); + const contractNode = findContractNode(ast, contractName); + if (!contractNode) return; + + const contractType = contractNode.kind; + // skip libraries and interfaces + if (contractType !== "contract" && contractType !== "abstract") return; + + const isSystem = ((): boolean => { + // if using the System suffix, assume its a system + if (contractName.endsWith("System") && contractName !== baseSystemName) return true; + + // otherwise check if we're inheriting from the base system + let extendsBaseSystem = false; + visit(contractNode, { + InheritanceSpecifier(node) { + if (node.baseName.namePath === baseSystemName) { + extendsBaseSystem = true; + } + }, + }); + return extendsBaseSystem && findSymbolImport(ast, baseSystemName)?.path === baseSystemPath; + })(); + + if (isSystem) { + return { contractType }; + } +} diff --git a/packages/world-module-callwithsignature/ts/build.ts b/packages/world-module-callwithsignature/ts/build.ts index 9f24536f54..267e5bfdb3 100644 --- a/packages/world-module-callwithsignature/ts/build.ts +++ b/packages/world-module-callwithsignature/ts/build.ts @@ -15,4 +15,6 @@ const configPath = "../mud.config"; const { default: config } = await import(configPath); const rootDir = path.dirname(path.join(__dirname, configPath)); -await Promise.all([tablegen({ rootDir, config }), worldgen({ rootDir, config })]); + +await tablegen({ rootDir, config }); +await worldgen({ rootDir, config }); diff --git a/packages/world-module-metadata/ts/build.ts b/packages/world-module-metadata/ts/build.ts index 9f24536f54..267e5bfdb3 100644 --- a/packages/world-module-metadata/ts/build.ts +++ b/packages/world-module-metadata/ts/build.ts @@ -15,4 +15,6 @@ const configPath = "../mud.config"; const { default: config } = await import(configPath); const rootDir = path.dirname(path.join(__dirname, configPath)); -await Promise.all([tablegen({ rootDir, config }), worldgen({ rootDir, config })]); + +await tablegen({ rootDir, config }); +await worldgen({ rootDir, config }); diff --git a/packages/world-modules/test/StandardDelegationsModule.t.sol b/packages/world-modules/test/StandardDelegationsModule.t.sol index 537fcced39..7b978ee023 100644 --- a/packages/world-modules/test/StandardDelegationsModule.t.sol +++ b/packages/world-modules/test/StandardDelegationsModule.t.sol @@ -147,7 +147,7 @@ contract StandardDelegationsModuleTest is Test, GasReporter { function testRegisterDelegationRevertInterfaceNotSupported() public { // Register a system that is not a delegation control system - System noDelegationControlSystem = new System(); + System noDelegationControlSystem = new WorldTestSystem(); ResourceId noDelegationControlId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "namespace", diff --git a/packages/world/src/System.sol b/packages/world/src/System.sol index f1add8cd23..74206bd060 100644 --- a/packages/world/src/System.sol +++ b/packages/world/src/System.sol @@ -9,6 +9,6 @@ import { WorldContextConsumer } from "./WorldContext.sol"; * @dev The System contract currently acts as an alias for `WorldContextConsumer`. * This structure is chosen for potential extensions in the future, where default functionality might be added to the System. */ -contract System is WorldContextConsumer { +abstract contract System is WorldContextConsumer { // Currently, no additional functionality is added. Future enhancements can be introduced here. } diff --git a/packages/world/test/World.t.sol b/packages/world/test/World.t.sol index 9d74439f56..5522abe3cd 100644 --- a/packages/world/test/World.t.sol +++ b/packages/world/test/World.t.sol @@ -530,7 +530,7 @@ contract WorldTest is Test, GasReporter { } function testRegisterSystem() public { - System system = new System(); + System system = new WorldTestSystem(); bytes14 namespace = ""; ResourceId namespaceId = WorldResourceIdLib.encodeNamespace(namespace); bytes16 name = "testSystem"; @@ -564,7 +564,7 @@ contract WorldTest is Test, GasReporter { assertTrue(ResourceAccess.get({ resourceId: namespaceId, caller: address(system) })); // Expect the registration to fail if the namespace does not exist yet - System newSystem = new System(); + System newSystem = new WorldTestSystem(); ResourceId invalidNamespaceSystemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "newNamespace", @@ -612,7 +612,7 @@ contract WorldTest is Test, GasReporter { world.registerSystem(tableId, newSystem, true); // Expect an error when registering a system in a namespace that is not owned by the caller - System yetAnotherSystem = new System(); + System yetAnotherSystem = new WorldTestSystem(); _expectAccessDenied(address(0x01), "", "", RESOURCE_NAMESPACE); world.registerSystem( WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "", name: "rootSystem" }), @@ -658,11 +658,11 @@ contract WorldTest is Test, GasReporter { world.registerNamespace(systemId.getNamespaceId()); // Register a system - System oldSystem = new System(); + System oldSystem = new WorldTestSystem(); world.registerSystem(systemId, oldSystem, true); // Upgrade the system and set public access to false - System newSystem = new System(); + System newSystem = new WorldTestSystem(); world.registerSystem(systemId, newSystem, false); // Expect the system address and public access to be updated in the System table @@ -712,7 +712,7 @@ contract WorldTest is Test, GasReporter { ); // Deploy a new system - System system = new System(); + System system = new WorldTestSystem(); // Expect an error when trying to register a system at the same ID vm.expectRevert( @@ -727,7 +727,7 @@ contract WorldTest is Test, GasReporter { // Register a new system ResourceId systemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "namespace2", name: "name" }); - world.registerSystem(systemId, new System(), false); + world.registerSystem(systemId, new WorldTestSystem(), false); // Expect an error when trying to register a table at the same ID vm.expectRevert( diff --git a/packages/world/ts/node/getSystemContracts.ts b/packages/world/ts/node/getSystemContracts.ts index c7f17a11cf..c6e151910d 100644 --- a/packages/world/ts/node/getSystemContracts.ts +++ b/packages/world/ts/node/getSystemContracts.ts @@ -1,6 +1,9 @@ import path from "node:path"; +import fs from "node:fs/promises"; import { World } from "../config/v2/output"; import { findSolidityFiles } from "./findSolidityFiles"; +import { parseSystem } from "@latticexyz/common/codegen"; +import { isDefined } from "@latticexyz/common/utils"; export type SystemContract = { readonly sourcePath: string; @@ -17,27 +20,26 @@ export async function getSystemContracts({ rootDir, config, }: GetSystemContractsOptions): Promise { - const solidityFiles = await findSolidityFiles({ + const filePaths = await findSolidityFiles({ cwd: rootDir, pattern: path.join(config.sourceDirectory, "**"), }); - // Get system labels from all namespaces - const configSystemLabels = Object.values(config.namespaces || {}).flatMap((namespace) => - Object.values(namespace.systems).map((system) => system.label), + const files = await Promise.all( + filePaths.map(async (file) => { + console.log("reading source for", file.filename); + const source = await fs.readFile(path.join(rootDir, file.filename), "utf-8"); + return { ...file, source }; + }), ); - return solidityFiles - .filter( - (file) => - // Include files with the System suffix and files defined in config - (file.basename.endsWith("System") || configSystemLabels.includes(file.basename)) && - // exclude the base System contract - file.basename !== "System" && - // exclude interfaces - !/^I[A-Z]/.test(file.basename), - ) + console.log("got files", filePaths); + + return files .map((file) => { + const parsedSystem = parseSystem(file.source, file.basename); + if (!parsedSystem) return; + const namespaceLabel = (() => { // TODO: remove `config.namespace` null check once this narrows properly if (!config.multipleNamespaces && config.namespace != null) return config.namespace; @@ -58,6 +60,7 @@ export async function getSystemContracts({ sourcePath: file.filename, namespaceLabel, systemLabel: file.basename, - }; - }); + } satisfies SystemContract; + }) + .filter(isDefined); } diff --git a/packages/world/ts/scripts/build.ts b/packages/world/ts/scripts/build.ts index ef89cdcffc..47c871c685 100644 --- a/packages/world/ts/scripts/build.ts +++ b/packages/world/ts/scripts/build.ts @@ -14,10 +14,8 @@ import config, { systemsConfig } from "../../mud.config"; const configPath = await resolveConfigPath(); const rootDir = path.dirname(configPath); -await Promise.all([ - tablegen({ rootDir, config }), - // until we get finer-grained control of for namespaces (source path, codegen) - // or being able to merge configs with strong types, we need to use a separate - // config for systems to maintain source locations - worldgen({ rootDir, config: systemsConfig }), -]); +await tablegen({ rootDir, config }); +// until we get finer-grained control of for namespaces (source path, codegen) +// or being able to merge configs with strong types, we need to use a separate +// config for systems to maintain source locations +await worldgen({ rootDir, config: systemsConfig }); From a858cb3d04ae0e0de58deb762fd11c771a9c0608 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Tue, 8 Apr 2025 11:34:46 +0100 Subject: [PATCH 05/10] rm log --- packages/world/ts/node/getSystemContracts.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/world/ts/node/getSystemContracts.ts b/packages/world/ts/node/getSystemContracts.ts index c6e151910d..0efd41da86 100644 --- a/packages/world/ts/node/getSystemContracts.ts +++ b/packages/world/ts/node/getSystemContracts.ts @@ -33,8 +33,6 @@ export async function getSystemContracts({ }), ); - console.log("got files", filePaths); - return files .map((file) => { const parsedSystem = parseSystem(file.source, file.basename); From c8d47e2f8bea6ec640d0a62d2964832cf00d5b03 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Tue, 8 Apr 2025 11:36:31 +0100 Subject: [PATCH 06/10] clarify the strategy --- packages/common/src/codegen/utils/parseSystem.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/common/src/codegen/utils/parseSystem.ts b/packages/common/src/codegen/utils/parseSystem.ts index e908b3708a..656a42fbd0 100644 --- a/packages/common/src/codegen/utils/parseSystem.ts +++ b/packages/common/src/codegen/utils/parseSystem.ts @@ -16,6 +16,7 @@ export function parseSystem( const contractType = contractNode.kind; // skip libraries and interfaces + // we allow abstract systems here so that we can create system libraries from them but without deploying them if (contractType !== "contract" && contractType !== "abstract") return; const isSystem = ((): boolean => { From 2b0053bd10b1536f73d67724d5534a899771451b Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Tue, 8 Apr 2025 11:39:27 +0100 Subject: [PATCH 07/10] update changeset --- .changeset/small-horses-own.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.changeset/small-horses-own.md b/.changeset/small-horses-own.md index 5a9755239c..a0382cdeef 100644 --- a/.changeset/small-horses-own.md +++ b/.changeset/small-horses-own.md @@ -1,5 +1,14 @@ --- "@latticexyz/world": patch +"@latticexyz/cli": patch --- -Support systems without the System suffix by adding them to the MUD config. +`mud` CLI commands will now recognize systems without a `System` suffix if they inherit directly from the base `System` imported from `@latticexyz/world/src/System.sol`. + +```solidity +import {System} from "@latticexyz/world/src/System.sol"; + +contract EntityProgram is System { + ... +} +``` From b498a08beec44a37b76991626c14f1908727363d Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Tue, 8 Apr 2025 11:44:45 +0100 Subject: [PATCH 08/10] update snapshots --- packages/store/ts/flattenStoreLogs.test.ts | 4 ++-- packages/store/ts/getStoreLogs.test.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/store/ts/flattenStoreLogs.test.ts b/packages/store/ts/flattenStoreLogs.test.ts index 6dcc0d87f0..ea25fea7b0 100644 --- a/packages/store/ts/flattenStoreLogs.test.ts +++ b/packages/store/ts/flattenStoreLogs.test.ts @@ -134,8 +134,8 @@ describe("flattenStoreLogs", async () => { "Store_SetRecord store__ResourceIds (0x746200000000000000000000000000005465727261696e000000000000000000)", "Store_SetRecord store__ResourceIds (0x737900000000000000000000000000004d6f766553797374656d000000000000)", "Store_SetRecord world__Systems (0x737900000000000000000000000000004d6f766553797374656d000000000000)", - "Store_SetRecord world__SystemRegistry (0x000000000000000000000000cbcdc66f9301ccf30b6b46efba8a3015d332dc13)", - "Store_SetRecord world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000cbcdc66f9301ccf30b6b46efba8a3015d332dc13)", + "Store_SetRecord world__SystemRegistry (0x00000000000000000000000040d21680e49a1f969a53760ff488a9d1ad01ca89)", + "Store_SetRecord world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000040d21680e49a1f969a53760ff488a9d1ad01ca89)", "Store_SetRecord world__FunctionSelector (0xb591186e00000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSignatur (0xb591186e00000000000000000000000000000000000000000000000000000000)", "Store_SetRecord store__Tables (0x7462000000000000000000000000000043616c6c576974685369676e61747572)", diff --git a/packages/store/ts/getStoreLogs.test.ts b/packages/store/ts/getStoreLogs.test.ts index 88608021ca..6cecdbb192 100644 --- a/packages/store/ts/getStoreLogs.test.ts +++ b/packages/store/ts/getStoreLogs.test.ts @@ -157,8 +157,8 @@ describe("getStoreLogs", async () => { "Store_SpliceStaticData store__ResourceIds (0x746200000000000000000000000000005465727261696e000000000000000000)", "Store_SpliceStaticData store__ResourceIds (0x737900000000000000000000000000004d6f766553797374656d000000000000)", "Store_SetRecord world__Systems (0x737900000000000000000000000000004d6f766553797374656d000000000000)", - "Store_SpliceStaticData world__SystemRegistry (0x000000000000000000000000cbcdc66f9301ccf30b6b46efba8a3015d332dc13)", - "Store_SpliceStaticData world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000cbcdc66f9301ccf30b6b46efba8a3015d332dc13)", + "Store_SpliceStaticData world__SystemRegistry (0x00000000000000000000000040d21680e49a1f969a53760ff488a9d1ad01ca89)", + "Store_SpliceStaticData world__ResourceAccess (0x6e73000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000040d21680e49a1f969a53760ff488a9d1ad01ca89)", "Store_SetRecord world__FunctionSelector (0xb591186e00000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSignatur (0xb591186e00000000000000000000000000000000000000000000000000000000)", "Store_SetRecord world__FunctionSignatur (0xb591186e00000000000000000000000000000000000000000000000000000000)", From a7d9a0c0b45a066f96009c305ee88b8073dd7049 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Tue, 8 Apr 2025 17:35:50 +0100 Subject: [PATCH 09/10] gas report --- packages/world/gas-report.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index fabd65da55..0954e44484 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -123,7 +123,7 @@ "file": "test/World.t.sol:WorldTest", "test": "testRegisterSystem", "name": "register a system", - "gasUsed": 185032 + "gasUsed": 185170 }, { "file": "test/World.t.sol:WorldTest", @@ -243,7 +243,7 @@ "file": "test/WorldProxy.t.sol:WorldProxyTest", "test": "testRegisterSystem", "name": "register a system", - "gasUsed": 189934 + "gasUsed": 190072 }, { "file": "test/WorldProxy.t.sol:WorldProxyTest", From 1d087e9e0a22d62114fe3503782a87940f80c2e8 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Fri, 11 Apr 2025 02:25:50 -0700 Subject: [PATCH 10/10] Update small-horses-own.md --- .changeset/small-horses-own.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.changeset/small-horses-own.md b/.changeset/small-horses-own.md index a0382cdeef..467bf4445f 100644 --- a/.changeset/small-horses-own.md +++ b/.changeset/small-horses-own.md @@ -3,7 +3,7 @@ "@latticexyz/cli": patch --- -`mud` CLI commands will now recognize systems without a `System` suffix if they inherit directly from the base `System` imported from `@latticexyz/world/src/System.sol`. +`mud` CLI commands will now recognize systems if they inherit directly from the base `System` imported from `@latticexyz/world/src/System.sol`, allowing you to write systems without a `System` suffix. ```solidity import {System} from "@latticexyz/world/src/System.sol"; @@ -12,3 +12,5 @@ contract EntityProgram is System { ... } ``` + +If you have contracts that inherit from the base `System` that aren't meant to be deployed, you can mark them as `abstract contract` or [disable the system's deploy via config](https://mud.dev/config/reference).