From 31cb43ae0525d2c4bc2e6caeee9ee420d20894e2 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 18 Jan 2024 10:47:25 +0000 Subject: [PATCH 1/9] remove system name from world function registration --- .../core/implementations/WorldRegistrationSystem.sol | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol index a4fe1f8ad1..8191152f21 100644 --- a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol +++ b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol @@ -175,14 +175,7 @@ contract WorldRegistrationSystem is System, IWorldErrors { // Compute global function selector string memory namespaceString = WorldResourceIdLib.toTrimmedString(systemId.getNamespace()); - string memory nameString = WorldResourceIdLib.toTrimmedString(systemId.getName()); - bytes memory worldFunctionSignature = abi.encodePacked( - namespaceString, - "_", - nameString, - "_", - systemFunctionSignature - ); + bytes memory worldFunctionSignature = abi.encodePacked(namespaceString, "_", systemFunctionSignature); worldFunctionSelector = bytes4(keccak256(worldFunctionSignature)); // Require the function selector to be globally unique From 15651295b1aa5f9de5314cd5e329a2f09d6c9daa Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 18 Jan 2024 16:51:41 +0000 Subject: [PATCH 2/9] remove system name from function names in codegen --- packages/world/ts/node/render-solidity/worldgen.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/world/ts/node/render-solidity/worldgen.ts b/packages/world/ts/node/render-solidity/worldgen.ts index a65d63ed8e..ebdd9914e2 100644 --- a/packages/world/ts/node/render-solidity/worldgen.ts +++ b/packages/world/ts/node/render-solidity/worldgen.ts @@ -42,11 +42,9 @@ export async function worldgen( } }); const systemInterfaceName = `I${system.basename}`; - // create an interface using the external functions and imports - const { name } = resolvedConfig.systems[system.basename]; const output = renderSystemInterface({ name: systemInterfaceName, - functionPrefix: config.namespace === "" ? "" : `${config.namespace}_${name}_`, + functionPrefix: config.namespace === "" ? "" : `${config.namespace}_`, functions, errors, imports, From 4f3b051a71775e57623188ecf2350d134bca4b11 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 18 Jan 2024 16:57:38 +0000 Subject: [PATCH 3/9] update tests --- packages/world/test/World.t.sol | 6 +++--- packages/world/test/WorldBalance.t.sol | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/world/test/World.t.sol b/packages/world/test/World.t.sol index 3e9f6db4d3..ee3e119f62 100644 --- a/packages/world/test/World.t.sol +++ b/packages/world/test/World.t.sol @@ -57,7 +57,7 @@ import { DelegationControlMock } from "./DelegationControlMock.sol"; import { createCoreModule } from "./createCoreModule.sol"; interface IWorldTestSystem { - function testNamespace_testSystem_err(string memory input) external pure; + function testNamespace_err(string memory input) external pure; } struct WorldTestSystemReturn { @@ -1483,7 +1483,7 @@ contract WorldTest is Test, GasReporter { bytes4 functionSelector = world.registerFunctionSelector(systemId, "msgSender()"); endGasReport(); - string memory expectedWorldFunctionSignature = "testNamespace_testSystem_msgSender()"; + string memory expectedWorldFunctionSignature = "testNamespace_msgSender()"; bytes4 expectedWorldFunctionSelector = bytes4(keccak256(abi.encodePacked(expectedWorldFunctionSignature))); assertEq(functionSelector, expectedWorldFunctionSelector, "wrong function selector returned"); @@ -1498,7 +1498,7 @@ contract WorldTest is Test, GasReporter { // Expect errors to be passed through vm.expectRevert(abi.encodeWithSelector(WorldTestSystem.WorldTestSystemError.selector, "test error")); - IWorldTestSystem(address(world)).testNamespace_testSystem_err("test error"); + IWorldTestSystem(address(world)).testNamespace_err("test error"); } function testRegisterRootFunctionSelector() public { diff --git a/packages/world/test/WorldBalance.t.sol b/packages/world/test/WorldBalance.t.sol index 65a6c84500..c9e4f43b1d 100644 --- a/packages/world/test/WorldBalance.t.sol +++ b/packages/world/test/WorldBalance.t.sol @@ -126,7 +126,7 @@ contract WorldBalanceTest is Test, GasReporter { // Call a function on a non-root system with value vm.deal(caller, value); vm.prank(caller); - (success, data) = address(world).call{ value: value }(abi.encodeWithSignature("namespace_testSystem_echoValue()")); + (success, data) = address(world).call{ value: value }(abi.encodeWithSignature("namespace_echoValue()")); assertTrue(success); assertEq(abi.decode(data, (uint256)), value); From b2fcaa626fc9943bd9a7db4354ef664630d33efc Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 18 Jan 2024 18:04:58 +0000 Subject: [PATCH 4/9] fix unique entity module --- packages/world-modules/src/interfaces/IUniqueEntitySystem.sol | 2 +- .../world-modules/src/modules/uniqueentity/getUniqueEntity.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/world-modules/src/interfaces/IUniqueEntitySystem.sol b/packages/world-modules/src/interfaces/IUniqueEntitySystem.sol index d9011e2201..6b8f8a1530 100644 --- a/packages/world-modules/src/interfaces/IUniqueEntitySystem.sol +++ b/packages/world-modules/src/interfaces/IUniqueEntitySystem.sol @@ -3,5 +3,5 @@ pragma solidity >=0.8.21; // TODO allow overriding namespace per-system (or a separate config for modules?) interface IUniqueEntitySystem { - function uniqueEntity_system_getUniqueEntity() external returns (bytes32 uniqueEntity); + function uniqueEntity_getUniqueEntity() external returns (bytes32 uniqueEntity); } diff --git a/packages/world-modules/src/modules/uniqueentity/getUniqueEntity.sol b/packages/world-modules/src/modules/uniqueentity/getUniqueEntity.sol index 62b99f6e8c..4ca9ed658a 100644 --- a/packages/world-modules/src/modules/uniqueentity/getUniqueEntity.sol +++ b/packages/world-modules/src/modules/uniqueentity/getUniqueEntity.sol @@ -23,5 +23,5 @@ function getUniqueEntity() returns (bytes32 uniqueEntity) { * Increment and get an entity nonce. */ function getUniqueEntity(IBaseWorld world) returns (bytes32 uniqueEntity) { - return IUniqueEntitySystem(address(world)).uniqueEntity_system_getUniqueEntity(); + return IUniqueEntitySystem(address(world)).uniqueEntity_getUniqueEntity(); } From 6e94d1b0140fdf677ef219dae24aa98a13a5e010 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 18 Jan 2024 18:07:42 +0000 Subject: [PATCH 5/9] gas report --- packages/world-modules/gas-report.json | 4 ++-- packages/world/gas-report.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/world-modules/gas-report.json b/packages/world-modules/gas-report.json index 9fa8b5c85b..b2f15685cd 100644 --- a/packages/world-modules/gas-report.json +++ b/packages/world-modules/gas-report.json @@ -303,7 +303,7 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 702723 + "gasUsed": 700820 }, { "file": "test/UniqueEntityModule.t.sol", @@ -315,7 +315,7 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 671743 + "gasUsed": 669840 }, { "file": "test/UniqueEntityModule.t.sol", diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index a3e650f9d0..a2586d8f59 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -105,7 +105,7 @@ "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 83123 + "gasUsed": 80572 }, { "file": "test/World.t.sol", From 55224b1730bec3807323a8ac7e772e28f3396d51 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 18 Jan 2024 18:17:44 +0000 Subject: [PATCH 6/9] fix example --- .../packages/contracts/src/interfaces/IChatNamespacedSystem.sol | 2 +- examples/minimal/packages/contracts/test/ChatNamespaced.t.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/minimal/packages/contracts/src/interfaces/IChatNamespacedSystem.sol b/examples/minimal/packages/contracts/src/interfaces/IChatNamespacedSystem.sol index ab8bd76b81..30cb3351b6 100644 --- a/examples/minimal/packages/contracts/src/interfaces/IChatNamespacedSystem.sol +++ b/examples/minimal/packages/contracts/src/interfaces/IChatNamespacedSystem.sol @@ -3,5 +3,5 @@ pragma solidity >=0.8.21; // TODO allow overriding namespace per-system interface IChatNamespacedSystem { - function namespace_ChatNamespaced_sendMessage(string memory message) external; + function namespace_sendMessage(string memory message) external; } diff --git a/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol b/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol index c87c3e4304..6a0a2f08a2 100644 --- a/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol +++ b/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol @@ -22,6 +22,6 @@ contract ChatNamespacedTest is MudTest { MessageTable.encodeLengths(value), MessageTable.encodeDynamic(value) ); - IChatNamespacedSystem(worldAddress).namespace_ChatNamespaced_sendMessage(value); + IChatNamespacedSystem(worldAddress).namespace_sendMessage(value); } } From a74ff63b12a4dbe55edbd934c62946fe22e59b3d Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 18 Jan 2024 18:29:58 +0000 Subject: [PATCH 7/9] this comment doesn't make sense --- .../packages/contracts/src/interfaces/IChatNamespacedSystem.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/minimal/packages/contracts/src/interfaces/IChatNamespacedSystem.sol b/examples/minimal/packages/contracts/src/interfaces/IChatNamespacedSystem.sol index 30cb3351b6..dd5d1fe42b 100644 --- a/examples/minimal/packages/contracts/src/interfaces/IChatNamespacedSystem.sol +++ b/examples/minimal/packages/contracts/src/interfaces/IChatNamespacedSystem.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.21; -// TODO allow overriding namespace per-system interface IChatNamespacedSystem { function namespace_sendMessage(string memory message) external; } From 24c201c9018ab76bcbf175f31127a7a7c43cdb5e Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 18 Jan 2024 10:34:40 -0800 Subject: [PATCH 8/9] Create bright-kangaroos-battle.md --- .changeset/bright-kangaroos-battle.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/bright-kangaroos-battle.md diff --git a/.changeset/bright-kangaroos-battle.md b/.changeset/bright-kangaroos-battle.md new file mode 100644 index 0000000000..6ec92c7364 --- /dev/null +++ b/.changeset/bright-kangaroos-battle.md @@ -0,0 +1,8 @@ +--- +"@latticexyz/world-modules": patch +"@latticexyz/world": major +--- + +Functions within namespaced systems are now registered on the world as `{namespace}_{functionName}` rather than `{namespace}_{systemName}_{functionName}`. This is more ergonomic and is more consistent with namespaced resources in other parts of the codebase (e.g. accessing tables in schemaful indexer). + +If you have a project using the `namespace` key in your `mud.config.ts` or are manually registering systems and function selectors on a namespace, you will likely need to codegen your system interfaces (`pnpm build`) and update any calls to these systems through the world's namespaced function signatures. From 4a3876bd24e5c2ad880f05b02557ef5a833f6ada Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Fri, 19 Jan 2024 11:28:12 +0000 Subject: [PATCH 9/9] double underscore --- .changeset/bright-kangaroos-battle.md | 2 +- .../contracts/src/interfaces/IChatNamespacedSystem.sol | 2 +- .../minimal/packages/contracts/test/ChatNamespaced.t.sol | 2 +- packages/world-modules/gas-report.json | 4 ++-- .../world-modules/src/interfaces/IUniqueEntitySystem.sol | 2 +- .../src/modules/uniqueentity/getUniqueEntity.sol | 2 +- .../core/implementations/WorldRegistrationSystem.sol | 2 +- packages/world/test/World.t.sol | 6 +++--- packages/world/test/WorldBalance.t.sol | 2 +- packages/world/ts/node/render-solidity/worldgen.ts | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.changeset/bright-kangaroos-battle.md b/.changeset/bright-kangaroos-battle.md index 6ec92c7364..bbbc1880c1 100644 --- a/.changeset/bright-kangaroos-battle.md +++ b/.changeset/bright-kangaroos-battle.md @@ -3,6 +3,6 @@ "@latticexyz/world": major --- -Functions within namespaced systems are now registered on the world as `{namespace}_{functionName}` rather than `{namespace}_{systemName}_{functionName}`. This is more ergonomic and is more consistent with namespaced resources in other parts of the codebase (e.g. accessing tables in schemaful indexer). +World function signatures for namespaced systems have changed from `{namespace}_{systemName}_{functionName}` to `{namespace}__{functionName}` (double underscore, no system name). This is more ergonomic and is more consistent with namespaced resources in other parts of the codebase (e.g. MUD config types, table names in the schemaful indexer). If you have a project using the `namespace` key in your `mud.config.ts` or are manually registering systems and function selectors on a namespace, you will likely need to codegen your system interfaces (`pnpm build`) and update any calls to these systems through the world's namespaced function signatures. diff --git a/examples/minimal/packages/contracts/src/interfaces/IChatNamespacedSystem.sol b/examples/minimal/packages/contracts/src/interfaces/IChatNamespacedSystem.sol index dd5d1fe42b..54a19f0379 100644 --- a/examples/minimal/packages/contracts/src/interfaces/IChatNamespacedSystem.sol +++ b/examples/minimal/packages/contracts/src/interfaces/IChatNamespacedSystem.sol @@ -2,5 +2,5 @@ pragma solidity >=0.8.21; interface IChatNamespacedSystem { - function namespace_sendMessage(string memory message) external; + function namespace__sendMessage(string memory message) external; } diff --git a/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol b/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol index 6a0a2f08a2..7c033b99d0 100644 --- a/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol +++ b/examples/minimal/packages/contracts/test/ChatNamespaced.t.sol @@ -22,6 +22,6 @@ contract ChatNamespacedTest is MudTest { MessageTable.encodeLengths(value), MessageTable.encodeDynamic(value) ); - IChatNamespacedSystem(worldAddress).namespace_sendMessage(value); + IChatNamespacedSystem(worldAddress).namespace__sendMessage(value); } } diff --git a/packages/world-modules/gas-report.json b/packages/world-modules/gas-report.json index cb5eba5075..581f86593e 100644 --- a/packages/world-modules/gas-report.json +++ b/packages/world-modules/gas-report.json @@ -309,7 +309,7 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 51027 + "gasUsed": 51026 }, { "file": "test/UniqueEntityModule.t.sol", @@ -321,6 +321,6 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 51027 + "gasUsed": 51026 } ] diff --git a/packages/world-modules/src/interfaces/IUniqueEntitySystem.sol b/packages/world-modules/src/interfaces/IUniqueEntitySystem.sol index 6b8f8a1530..80a511528a 100644 --- a/packages/world-modules/src/interfaces/IUniqueEntitySystem.sol +++ b/packages/world-modules/src/interfaces/IUniqueEntitySystem.sol @@ -3,5 +3,5 @@ pragma solidity >=0.8.21; // TODO allow overriding namespace per-system (or a separate config for modules?) interface IUniqueEntitySystem { - function uniqueEntity_getUniqueEntity() external returns (bytes32 uniqueEntity); + function uniqueEntity__getUniqueEntity() external returns (bytes32 uniqueEntity); } diff --git a/packages/world-modules/src/modules/uniqueentity/getUniqueEntity.sol b/packages/world-modules/src/modules/uniqueentity/getUniqueEntity.sol index 4ca9ed658a..7894132f50 100644 --- a/packages/world-modules/src/modules/uniqueentity/getUniqueEntity.sol +++ b/packages/world-modules/src/modules/uniqueentity/getUniqueEntity.sol @@ -23,5 +23,5 @@ function getUniqueEntity() returns (bytes32 uniqueEntity) { * Increment and get an entity nonce. */ function getUniqueEntity(IBaseWorld world) returns (bytes32 uniqueEntity) { - return IUniqueEntitySystem(address(world)).uniqueEntity_getUniqueEntity(); + return IUniqueEntitySystem(address(world)).uniqueEntity__getUniqueEntity(); } diff --git a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol index a9a6be1a85..d416837b96 100644 --- a/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol +++ b/packages/world/src/modules/core/implementations/WorldRegistrationSystem.sol @@ -195,7 +195,7 @@ contract WorldRegistrationSystem is System, IWorldErrors, LimitedCallContext { // Compute global function selector string memory namespaceString = WorldResourceIdLib.toTrimmedString(systemId.getNamespace()); - bytes memory worldFunctionSignature = abi.encodePacked(namespaceString, "_", systemFunctionSignature); + bytes memory worldFunctionSignature = abi.encodePacked(namespaceString, "__", systemFunctionSignature); worldFunctionSelector = bytes4(keccak256(worldFunctionSignature)); // Require the function selector to be globally unique diff --git a/packages/world/test/World.t.sol b/packages/world/test/World.t.sol index 0d6ef42022..179ccbc6b2 100644 --- a/packages/world/test/World.t.sol +++ b/packages/world/test/World.t.sol @@ -57,7 +57,7 @@ import { DelegationControlMock } from "./DelegationControlMock.sol"; import { createCoreModule } from "./createCoreModule.sol"; interface IWorldTestSystem { - function testNamespace_err(string memory input) external pure; + function testNamespace__err(string memory input) external pure; } struct WorldTestSystemReturn { @@ -1487,7 +1487,7 @@ contract WorldTest is Test, GasReporter { bytes4 functionSelector = world.registerFunctionSelector(systemId, "msgSender()"); endGasReport(); - string memory expectedWorldFunctionSignature = "testNamespace_msgSender()"; + string memory expectedWorldFunctionSignature = "testNamespace__msgSender()"; bytes4 expectedWorldFunctionSelector = bytes4(keccak256(abi.encodePacked(expectedWorldFunctionSignature))); assertEq(functionSelector, expectedWorldFunctionSelector, "wrong function selector returned"); @@ -1502,7 +1502,7 @@ contract WorldTest is Test, GasReporter { // Expect errors to be passed through vm.expectRevert(abi.encodeWithSelector(WorldTestSystem.WorldTestSystemError.selector, "test error")); - IWorldTestSystem(address(world)).testNamespace_err("test error"); + IWorldTestSystem(address(world)).testNamespace__err("test error"); } function testRegisterRootFunctionSelector() public { diff --git a/packages/world/test/WorldBalance.t.sol b/packages/world/test/WorldBalance.t.sol index c9e4f43b1d..30f494fe87 100644 --- a/packages/world/test/WorldBalance.t.sol +++ b/packages/world/test/WorldBalance.t.sol @@ -126,7 +126,7 @@ contract WorldBalanceTest is Test, GasReporter { // Call a function on a non-root system with value vm.deal(caller, value); vm.prank(caller); - (success, data) = address(world).call{ value: value }(abi.encodeWithSignature("namespace_echoValue()")); + (success, data) = address(world).call{ value: value }(abi.encodeWithSignature("namespace__echoValue()")); assertTrue(success); assertEq(abi.decode(data, (uint256)), value); diff --git a/packages/world/ts/node/render-solidity/worldgen.ts b/packages/world/ts/node/render-solidity/worldgen.ts index ebdd9914e2..f9dbf77d37 100644 --- a/packages/world/ts/node/render-solidity/worldgen.ts +++ b/packages/world/ts/node/render-solidity/worldgen.ts @@ -44,7 +44,7 @@ export async function worldgen( const systemInterfaceName = `I${system.basename}`; const output = renderSystemInterface({ name: systemInterfaceName, - functionPrefix: config.namespace === "" ? "" : `${config.namespace}_`, + functionPrefix: config.namespace === "" ? "" : `${config.namespace}__`, functions, errors, imports,