Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(world): remove system name from function signatures/selectors [M-05] #2160

Merged
merged 13 commits into from
Jan 22, 2024
8 changes: 8 additions & 0 deletions .changeset/bright-kangaroos-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@latticexyz/world-modules": patch
"@latticexyz/world": major
---

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.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to bubble this up as a breaking change aside from major tag?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

major should be only breaking changes, no other way make it more prominent unfortunately

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: MIT
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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
4 changes: 2 additions & 2 deletions packages/world-modules/gas-report.json
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@
"file": "test/UniqueEntityModule.t.sol",
"test": "testInstall",
"name": "install unique entity module",
"gasUsed": 704240
"gasUsed": 702338
},
{
"file": "test/UniqueEntityModule.t.sol",
Expand All @@ -315,7 +315,7 @@
"file": "test/UniqueEntityModule.t.sol",
"test": "testInstallRoot",
"name": "installRoot unique entity module",
"gasUsed": 673144
"gasUsed": 671242
},
{
"file": "test/UniqueEntityModule.t.sol",
Expand Down
2 changes: 1 addition & 1 deletion packages/world/gas-report.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
"file": "test/World.t.sol",
"test": "testRegisterFunctionSelector",
"name": "Register a function selector",
"gasUsed": 84519
"gasUsed": 81969
},
{
"file": "test/World.t.sol",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,7 @@ contract WorldRegistrationSystem is System, IWorldErrors, LimitedCallContext {

// 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
Expand Down
6 changes: 3 additions & 3 deletions packages/world/test/World.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -1487,7 +1487,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");

Expand All @@ -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_testSystem_err("test error");
IWorldTestSystem(address(world)).testNamespace__err("test error");
}

function testRegisterRootFunctionSelector() public {
Expand Down
2 changes: 1 addition & 1 deletion packages/world/test/WorldBalance.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
4 changes: 1 addition & 3 deletions packages/world/ts/node/render-solidity/worldgen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading