From 943d536c418d0ed8214a1bfad471d4a13768a4b6 Mon Sep 17 00:00:00 2001 From: Fraser Scott Date: Thu, 25 Apr 2024 14:51:21 +0100 Subject: [PATCH 01/13] feat(store): table ID is unique on namespace and name --- packages/store/gas-report.json | 60 ++--- packages/store/mud.config.ts | 7 + packages/store/src/ResourceId.sol | 9 + packages/store/src/StoreCore.sol | 8 +- packages/store/src/codegen/index.sol | 1 + .../src/codegen/tables/ResourceNames.sol | 211 ++++++++++++++++++ packages/world-modules/gas-report.json | 24 +- packages/world/gas-report.json | 8 +- 8 files changed, 281 insertions(+), 47 deletions(-) create mode 100644 packages/store/src/codegen/tables/ResourceNames.sol diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index e4ba19f8c0..6b4a02dae1 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -21,7 +21,7 @@ "file": "test/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 56118 + "gasUsed": 56119 }, { "file": "test/Callbacks.t.sol", @@ -33,7 +33,7 @@ "file": "test/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 32402 + "gasUsed": 32404 }, { "file": "test/EncodedLengths.t.sol", @@ -357,7 +357,7 @@ "file": "test/KeyEncoding.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register KeyEncoding table", - "gasUsed": 717787 + "gasUsed": 749827 }, { "file": "test/Mixed.t.sol", @@ -651,31 +651,31 @@ "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access non-existing record", - "gasUsed": 7073 + "gasUsed": 7074 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access static field of non-existing record", - "gasUsed": 1330 + "gasUsed": 1331 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access dynamic field of non-existing record", - "gasUsed": 2062 + "gasUsed": 2063 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access length of dynamic field of non-existing record", - "gasUsed": 1158 + "gasUsed": 1159 }, { "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 7373 + "gasUsed": 7375 }, { "file": "test/StoreCoreGas.t.sol", @@ -759,19 +759,19 @@ "file": "test/StoreCoreGas.t.sol", "test": "testPushToDynamicField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 9539 + "gasUsed": 9541 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToDynamicField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 32211 + "gasUsed": 32212 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 647841 + "gasUsed": 679869 }, { "file": "test/StoreCoreGas.t.sol", @@ -783,7 +783,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get value schema (warm)", - "gasUsed": 1441 + "gasUsed": 1442 }, { "file": "test/StoreCoreGas.t.sol", @@ -795,7 +795,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 101866 + "gasUsed": 101869 }, { "file": "test/StoreCoreGas.t.sol", @@ -813,31 +813,31 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "compare: Set complex record with dynamic data using abi.encode", - "gasUsed": 267534 + "gasUsed": 267535 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "set dynamic length of dynamic index 0", - "gasUsed": 22867 + "gasUsed": 22868 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "set dynamic length of dynamic index 1", - "gasUsed": 967 + "gasUsed": 968 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "reduce dynamic length of dynamic index 0", - "gasUsed": 957 + "gasUsed": 958 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 31026 + "gasUsed": 31027 }, { "file": "test/StoreCoreGas.t.sol", @@ -849,7 +849,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 29609 + "gasUsed": 29611 }, { "file": "test/StoreCoreGas.t.sol", @@ -861,43 +861,43 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 54022 + "gasUsed": 54024 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, first dynamic field)", - "gasUsed": 2227 + "gasUsed": 2228 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 32246 + "gasUsed": 32248 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, second dynamic field)", - "gasUsed": 2229 + "gasUsed": 2230 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 32142 + "gasUsed": 32144 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "get static record (1 slot)", - "gasUsed": 1551 + "gasUsed": 1552 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 54649 + "gasUsed": 54651 }, { "file": "test/StoreCoreGas.t.sol", @@ -915,13 +915,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInDynamicField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 8899 + "gasUsed": 8900 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInDynamicField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 9342 + "gasUsed": 9344 }, { "file": "test/StoreHook.t.sol", @@ -1113,13 +1113,13 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 443849 + "gasUsed": 475874 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 32824 + "gasUsed": 32826 }, { "file": "test/Vector2.t.sol", diff --git a/packages/store/mud.config.ts b/packages/store/mud.config.ts index c5fd5335e1..471db5c640 100644 --- a/packages/store/mud.config.ts +++ b/packages/store/mud.config.ts @@ -36,6 +36,13 @@ export default defineStore({ }, key: ["resourceId"], }, + ResourceNames: { + schema: { + name: "bytes30", + exists: "bool", + }, + key: ["name"], + }, // The Hooks table is a generic table used by the `filterFromList` util in `Hook.sol` Hooks: { schema: { diff --git a/packages/store/src/ResourceId.sol b/packages/store/src/ResourceId.sol index f0905e1305..5916c6baeb 100644 --- a/packages/store/src/ResourceId.sol +++ b/packages/store/src/ResourceId.sol @@ -45,4 +45,13 @@ library ResourceIdInstance { function getType(ResourceId resourceId) internal pure returns (bytes2) { return bytes2(ResourceId.unwrap(resourceId)); } + + /** + * @notice Get the name from a resource ID. + * @param resourceId The resource ID. + * @return A 30-byte name. + */ + function getStoreName(ResourceId resourceId) internal pure returns (bytes30) { + return bytes30(ResourceId.unwrap(resourceId) << (TYPE_BITS)); + } } diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index ddd38a60b1..bd367df36b 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -9,7 +9,7 @@ import { FieldLayout, FieldLayoutLib } from "./FieldLayout.sol"; import { Schema, SchemaLib } from "./Schema.sol"; import { EncodedLengths } from "./EncodedLengths.sol"; import { Slice, SliceLib } from "./Slice.sol"; -import { Tables, ResourceIds, StoreHooks } from "./codegen/index.sol"; +import { ResourceNames, Tables, ResourceIds, StoreHooks } from "./codegen/index.sol"; import { IStoreErrors } from "./IStoreErrors.sol"; import { IStoreHook } from "./IStoreHook.sol"; import { StoreSwitch } from "./StoreSwitch.sol"; @@ -78,6 +78,7 @@ library StoreCore { ResourceIds._setExists(ResourceIds._tableId, true); // Now we can register the rest of the core tables as regular tables. + ResourceNames.register(); StoreHooks.register(); } @@ -213,12 +214,17 @@ library StoreCore { if (ResourceIds._getExists(tableId)) { revert IStoreErrors.Store_TableAlreadyExists(tableId, string(abi.encodePacked(tableId))); } + // Verify there is no resource with this name yet + if (ResourceNames._getExists(tableId.getStoreName())) { + revert IStoreErrors.Store_TableAlreadyExists(tableId, string(abi.encodePacked(tableId))); + } // Register the table metadata Tables._set(tableId, fieldLayout, keySchema, valueSchema, abi.encode(keyNames), abi.encode(fieldNames)); // Register the table ID ResourceIds._setExists(tableId, true); + ResourceNames._setExists(tableId.getStoreName(), true); } /************************************************************************ diff --git a/packages/store/src/codegen/index.sol b/packages/store/src/codegen/index.sol index 062209e3db..80ad244524 100644 --- a/packages/store/src/codegen/index.sol +++ b/packages/store/src/codegen/index.sol @@ -6,4 +6,5 @@ pragma solidity >=0.8.24; import { StoreHooks } from "./tables/StoreHooks.sol"; import { Tables, TablesData } from "./tables/Tables.sol"; import { ResourceIds } from "./tables/ResourceIds.sol"; +import { ResourceNames } from "./tables/ResourceNames.sol"; import { Hooks } from "./tables/Hooks.sol"; diff --git a/packages/store/src/codegen/tables/ResourceNames.sol b/packages/store/src/codegen/tables/ResourceNames.sol new file mode 100644 index 0000000000..7c1cebc7ad --- /dev/null +++ b/packages/store/src/codegen/tables/ResourceNames.sol @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +/* Autogenerated file. Do not edit manually. */ + +// Import store internals +import { IStore } from "../../IStore.sol"; +import { StoreSwitch } from "../../StoreSwitch.sol"; +import { StoreCore } from "../../StoreCore.sol"; +import { Bytes } from "../../Bytes.sol"; +import { Memory } from "../../Memory.sol"; +import { SliceLib } from "../../Slice.sol"; +import { EncodeArray } from "../../tightcoder/EncodeArray.sol"; +import { FieldLayout } from "../../FieldLayout.sol"; +import { Schema } from "../../Schema.sol"; +import { EncodedLengths, EncodedLengthsLib } from "../../EncodedLengths.sol"; +import { ResourceId } from "../../ResourceId.sol"; + +library ResourceNames { + // Hex below is the result of `WorldResourceIdLib.encode({ namespace: "store", name: "ResourceNames", typeId: RESOURCE_TABLE });` + ResourceId constant _tableId = ResourceId.wrap(0x746273746f72650000000000000000005265736f757263654e616d6573000000); + + FieldLayout constant _fieldLayout = + FieldLayout.wrap(0x0001010001000000000000000000000000000000000000000000000000000000); + + // Hex-encoded key schema of (bytes30) + Schema constant _keySchema = Schema.wrap(0x001e01005d000000000000000000000000000000000000000000000000000000); + // Hex-encoded value schema of (bool) + Schema constant _valueSchema = Schema.wrap(0x0001010060000000000000000000000000000000000000000000000000000000); + + /** + * @notice Get the table's key field names. + * @return keyNames An array of strings with the names of key fields. + */ + function getKeyNames() internal pure returns (string[] memory keyNames) { + keyNames = new string[](1); + keyNames[0] = "name"; + } + + /** + * @notice Get the table's value field names. + * @return fieldNames An array of strings with the names of value fields. + */ + function getFieldNames() internal pure returns (string[] memory fieldNames) { + fieldNames = new string[](1); + fieldNames[0] = "exists"; + } + + /** + * @notice Register the table with its config. + */ + function register() internal { + StoreSwitch.registerTable(_tableId, _fieldLayout, _keySchema, _valueSchema, getKeyNames(), getFieldNames()); + } + + /** + * @notice Register the table with its config. + */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, _keySchema, _valueSchema, getKeyNames(), getFieldNames()); + } + + /** + * @notice Get exists. + */ + function getExists(bytes30 name) internal view returns (bool exists) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(name); + + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + + /** + * @notice Get exists. + */ + function _getExists(bytes30 name) internal view returns (bool exists) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(name); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + + /** + * @notice Get exists. + */ + function get(bytes30 name) internal view returns (bool exists) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(name); + + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + + /** + * @notice Get exists. + */ + function _get(bytes30 name) internal view returns (bool exists) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(name); + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (_toBool(uint8(bytes1(_blob)))); + } + + /** + * @notice Set exists. + */ + function setExists(bytes30 name, bool exists) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(name); + + StoreSwitch.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); + } + + /** + * @notice Set exists. + */ + function _setExists(bytes30 name, bool exists) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(name); + + StoreCore.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); + } + + /** + * @notice Set exists. + */ + function set(bytes30 name, bool exists) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(name); + + StoreSwitch.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); + } + + /** + * @notice Set exists. + */ + function _set(bytes30 name, bool exists) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(name); + + StoreCore.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); + } + + /** + * @notice Delete all data for given keys. + */ + function deleteRecord(bytes30 name) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(name); + + StoreSwitch.deleteRecord(_tableId, _keyTuple); + } + + /** + * @notice Delete all data for given keys. + */ + function _deleteRecord(bytes30 name) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(name); + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** + * @notice Tightly pack static (fixed length) data using this table's schema. + * @return The static data, encoded into a sequence of bytes. + */ + function encodeStatic(bool exists) internal pure returns (bytes memory) { + return abi.encodePacked(exists); + } + + /** + * @notice Encode all of a record's fields. + * @return The static (fixed length) data, encoded into a sequence of bytes. + * @return The lengths of the dynamic fields (packed into a single bytes32 value). + * @return The dynamic (variable length) data, encoded into a sequence of bytes. + */ + function encode(bool exists) internal pure returns (bytes memory, EncodedLengths, bytes memory) { + bytes memory _staticData = encodeStatic(exists); + + EncodedLengths _encodedLengths; + bytes memory _dynamicData; + + return (_staticData, _encodedLengths, _dynamicData); + } + + /** + * @notice Encode keys as a bytes32 array using this table's field layout. + */ + function encodeKeyTuple(bytes30 name) internal pure returns (bytes32[] memory) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = bytes32(name); + + return _keyTuple; + } +} + +/** + * @notice Cast a value to a bool. + * @dev Boolean values are encoded as uint8 (1 = true, 0 = false), but Solidity doesn't allow casting between uint8 and bool. + * @param value The uint8 value to convert. + * @return result The boolean value. + */ +function _toBool(uint8 value) pure returns (bool result) { + assembly { + result := value + } +} diff --git a/packages/world-modules/gas-report.json b/packages/world-modules/gas-report.json index 853c07d2d5..8a0d17f9ce 100644 --- a/packages/world-modules/gas-report.json +++ b/packages/world-modules/gas-report.json @@ -3,7 +3,7 @@ "file": "test/CallWithSignatureModule.t.sol", "test": "testInstallRoot", "name": "install delegation module", - "gasUsed": 687912 + "gasUsed": 719957 }, { "file": "test/CallWithSignatureModule.t.sol", @@ -87,13 +87,13 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1456815 + "gasUsed": 1518915 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1456815 + "gasUsed": 1518915 }, { "file": "test/KeysInTableModule.t.sol", @@ -105,13 +105,13 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1456815 + "gasUsed": 1518915 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1456815 + "gasUsed": 1518915 }, { "file": "test/KeysInTableModule.t.sol", @@ -129,7 +129,7 @@ "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1456815 + "gasUsed": 1518915 }, { "file": "test/KeysInTableModule.t.sol", @@ -147,7 +147,7 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 715762 + "gasUsed": 747810 }, { "file": "test/KeysWithValueModule.t.sol", @@ -165,7 +165,7 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 715762 + "gasUsed": 747810 }, { "file": "test/KeysWithValueModule.t.sol", @@ -177,7 +177,7 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 715762 + "gasUsed": 747810 }, { "file": "test/KeysWithValueModule.t.sol", @@ -195,7 +195,7 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 715762 + "gasUsed": 747810 }, { "file": "test/KeysWithValueModule.t.sol", @@ -315,7 +315,7 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 715495 + "gasUsed": 747548 }, { "file": "test/UniqueEntityModule.t.sol", @@ -327,7 +327,7 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 685964 + "gasUsed": 718008 }, { "file": "test/UniqueEntityModule.t.sol", diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 131e2971f3..9b72186c15 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -63,7 +63,7 @@ "file": "test/Factories.t.sol", "test": "testWorldFactoryGas", "name": "deploy world via WorldFactory", - "gasUsed": 12805251 + "gasUsed": 13599502 }, { "file": "test/World.t.sol", @@ -129,7 +129,7 @@ "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 569676 + "gasUsed": 601725 }, { "file": "test/World.t.sol", @@ -249,7 +249,7 @@ "file": "test/WorldProxy.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 574686 + "gasUsed": 606735 }, { "file": "test/WorldProxy.t.sol", @@ -285,7 +285,7 @@ "file": "test/WorldProxyFactory.t.sol", "test": "testWorldProxyFactoryGas", "name": "deploy world via WorldProxyFactory", - "gasUsed": 9100791 + "gasUsed": 9895042 }, { "file": "test/WorldProxyFactory.t.sol", From 9f1b338154b815f4afe6eb038c5527b4ee511ca9 Mon Sep 17 00:00:00 2001 From: Fraser Scott Date: Thu, 25 Apr 2024 14:55:48 +0100 Subject: [PATCH 02/13] fix: set tables and resourceIds as exists --- packages/store/src/StoreCore.sol | 3 +++ packages/world/gas-report.json | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index bd367df36b..0ca338b929 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -79,6 +79,9 @@ library StoreCore { // Now we can register the rest of the core tables as regular tables. ResourceNames.register(); + ResourceNames._setExists(Tables._tableId.getStoreName(), true); + ResourceNames._setExists(ResourceIds._tableId.getStoreName(), true); + StoreHooks.register(); } diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 9b72186c15..2d9bbe76de 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -63,7 +63,7 @@ "file": "test/Factories.t.sol", "test": "testWorldFactoryGas", "name": "deploy world via WorldFactory", - "gasUsed": 13599502 + "gasUsed": 13657681 }, { "file": "test/World.t.sol", @@ -285,7 +285,7 @@ "file": "test/WorldProxyFactory.t.sol", "test": "testWorldProxyFactoryGas", "name": "deploy world via WorldProxyFactory", - "gasUsed": 9895042 + "gasUsed": 9953221 }, { "file": "test/WorldProxyFactory.t.sol", From e0f967b5405c2172fdad3e9eb9875dba898d4960 Mon Sep 17 00:00:00 2001 From: Fraser Scott Date: Thu, 25 Apr 2024 15:27:58 +0100 Subject: [PATCH 03/13] refactor: remove index table --- packages/store/gas-report.json | 120 ++++++++++++------------- packages/store/mud.config.ts | 7 -- packages/store/src/ResourceId.sol | 2 +- packages/store/src/StoreCore.sol | 28 +++--- packages/store/src/codegen/index.sol | 1 - packages/world-modules/gas-report.json | 24 ++--- packages/world/gas-report.json | 8 +- 7 files changed, 94 insertions(+), 96 deletions(-) diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 6b4a02dae1..b8f83a8666 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -21,7 +21,7 @@ "file": "test/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 56119 + "gasUsed": 56133 }, { "file": "test/Callbacks.t.sol", @@ -33,7 +33,7 @@ "file": "test/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 32404 + "gasUsed": 32417 }, { "file": "test/EncodedLengths.t.sol", @@ -357,7 +357,7 @@ "file": "test/KeyEncoding.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register KeyEncoding table", - "gasUsed": 749827 + "gasUsed": 721046 }, { "file": "test/Mixed.t.sol", @@ -369,19 +369,19 @@ "file": "test/Mixed.t.sol", "test": "testDeleteExternalCold", "name": "delete record from Mixed (external, cold)", - "gasUsed": 23515 + "gasUsed": 23530 }, { "file": "test/Mixed.t.sol", "test": "testDeleteInternalCold", "name": "delete record from Mixed (internal, cold)", - "gasUsed": 18724 + "gasUsed": 18739 }, { "file": "test/Mixed.t.sol", "test": "testSetGetDeleteExternal", "name": "set record in Mixed (external, cold)", - "gasUsed": 107665 + "gasUsed": 107680 }, { "file": "test/Mixed.t.sol", @@ -393,13 +393,13 @@ "file": "test/Mixed.t.sol", "test": "testSetGetDeleteExternal", "name": "delete record from Mixed (external, warm)", - "gasUsed": 7826 + "gasUsed": 7841 }, { "file": "test/Mixed.t.sol", "test": "testSetGetDeleteInternal", "name": "set record in Mixed (internal, cold)", - "gasUsed": 102831 + "gasUsed": 102846 }, { "file": "test/Mixed.t.sol", @@ -411,7 +411,7 @@ "file": "test/Mixed.t.sol", "test": "testSetGetDeleteInternal", "name": "delete record from Mixed (internal, warm)", - "gasUsed": 7033 + "gasUsed": 7048 }, { "file": "test/ResourceId.t.sol", @@ -627,43 +627,43 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 18107 + "gasUsed": 18122 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 12114 + "gasUsed": 12129 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 15876 + "gasUsed": 15891 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 11883 + "gasUsed": 11898 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access non-existing record", - "gasUsed": 7074 + "gasUsed": 7073 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access static field of non-existing record", - "gasUsed": 1331 + "gasUsed": 1330 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access dynamic field of non-existing record", - "gasUsed": 2063 + "gasUsed": 2062 }, { "file": "test/StoreCoreGas.t.sol", @@ -675,13 +675,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 7375 + "gasUsed": 7388 }, { "file": "test/StoreCoreGas.t.sol", "test": "testDeleteDataOffchainTable", "name": "StoreCore: delete record in offchain table", - "gasUsed": 28225 + "gasUsed": 28240 }, { "file": "test/StoreCoreGas.t.sol", @@ -711,79 +711,79 @@ "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 56589 + "gasUsed": 56619 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 98286 + "gasUsed": 98316 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 52904 + "gasUsed": 52934 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 47489 + "gasUsed": 47519 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 56589 + "gasUsed": 56619 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 191643 + "gasUsed": 191673 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 60374 + "gasUsed": 60404 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 49266 + "gasUsed": 49296 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToDynamicField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 9541 + "gasUsed": 9554 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToDynamicField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 32212 + "gasUsed": 32226 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 679869 + "gasUsed": 651094 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get field layout (warm)", - "gasUsed": 508 + "gasUsed": 509 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get value schema (warm)", - "gasUsed": 1442 + "gasUsed": 1441 }, { "file": "test/StoreCoreGas.t.sol", @@ -795,13 +795,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 101869 + "gasUsed": 101882 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "get complex record with dynamic data (4 slots)", - "gasUsed": 4235 + "gasUsed": 4234 }, { "file": "test/StoreCoreGas.t.sol", @@ -819,7 +819,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "set dynamic length of dynamic index 0", - "gasUsed": 22868 + "gasUsed": 22867 }, { "file": "test/StoreCoreGas.t.sol", @@ -837,7 +837,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 31027 + "gasUsed": 31041 }, { "file": "test/StoreCoreGas.t.sol", @@ -849,7 +849,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 29611 + "gasUsed": 29624 }, { "file": "test/StoreCoreGas.t.sol", @@ -861,31 +861,31 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 54024 + "gasUsed": 54037 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, first dynamic field)", - "gasUsed": 2228 + "gasUsed": 2227 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 32248 + "gasUsed": 32262 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, second dynamic field)", - "gasUsed": 2230 + "gasUsed": 2229 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 32144 + "gasUsed": 32157 }, { "file": "test/StoreCoreGas.t.sol", @@ -897,7 +897,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 54651 + "gasUsed": 54665 }, { "file": "test/StoreCoreGas.t.sol", @@ -909,19 +909,19 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetDataOffchainTable", "name": "StoreCore: set record in offchain table", - "gasUsed": 32517 + "gasUsed": 32532 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInDynamicField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 8900 + "gasUsed": 8914 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInDynamicField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 9344 + "gasUsed": 9357 }, { "file": "test/StoreHook.t.sol", @@ -951,13 +951,13 @@ "file": "test/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 58112 + "gasUsed": 58127 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 58112 + "gasUsed": 58127 }, { "file": "test/StoreHooks.t.sol", @@ -969,55 +969,55 @@ "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 12491 + "gasUsed": 12506 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 9795 + "gasUsed": 9810 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 10507 + "gasUsed": 10522 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 29741 + "gasUsed": 29756 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: delete record (warm)", - "gasUsed": 9552 + "gasUsed": 9567 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 30255 + "gasUsed": 30270 }, { "file": "test/StoreHooks.t.sol", "test": "testThreeSlots", "name": "StoreHooks: set field with three elements (cold)", - "gasUsed": 80803 + "gasUsed": 80818 }, { "file": "test/StoreHooks.t.sol", "test": "testTwoSlots", "name": "StoreHooks: set field with two elements (cold)", - "gasUsed": 80715 + "gasUsed": 80730 }, { "file": "test/StoreHooksColdLoad.t.sol", "test": "testDelete", "name": "StoreHooks: delete record (cold)", - "gasUsed": 18424 + "gasUsed": 18439 }, { "file": "test/StoreHooksColdLoad.t.sol", @@ -1041,13 +1041,13 @@ "file": "test/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 18231 + "gasUsed": 18246 }, { "file": "test/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 20194 + "gasUsed": 20209 }, { "file": "test/StoreSwitch.t.sol", @@ -1113,13 +1113,13 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 475874 + "gasUsed": 447101 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 32826 + "gasUsed": 32839 }, { "file": "test/Vector2.t.sol", diff --git a/packages/store/mud.config.ts b/packages/store/mud.config.ts index 471db5c640..c5fd5335e1 100644 --- a/packages/store/mud.config.ts +++ b/packages/store/mud.config.ts @@ -36,13 +36,6 @@ export default defineStore({ }, key: ["resourceId"], }, - ResourceNames: { - schema: { - name: "bytes30", - exists: "bool", - }, - key: ["name"], - }, // The Hooks table is a generic table used by the `filterFromList` util in `Hook.sol` Hooks: { schema: { diff --git a/packages/store/src/ResourceId.sol b/packages/store/src/ResourceId.sol index 5916c6baeb..a332b6ee68 100644 --- a/packages/store/src/ResourceId.sol +++ b/packages/store/src/ResourceId.sol @@ -51,7 +51,7 @@ library ResourceIdInstance { * @param resourceId The resource ID. * @return A 30-byte name. */ - function getStoreName(ResourceId resourceId) internal pure returns (bytes30) { + function getNameStore(ResourceId resourceId) internal pure returns (bytes30) { return bytes30(ResourceId.unwrap(resourceId) << (TYPE_BITS)); } } diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index 0ca338b929..47d79b271a 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -9,13 +9,13 @@ import { FieldLayout, FieldLayoutLib } from "./FieldLayout.sol"; import { Schema, SchemaLib } from "./Schema.sol"; import { EncodedLengths } from "./EncodedLengths.sol"; import { Slice, SliceLib } from "./Slice.sol"; -import { ResourceNames, Tables, ResourceIds, StoreHooks } from "./codegen/index.sol"; +import { Tables, ResourceIds, StoreHooks } from "./codegen/index.sol"; import { IStoreErrors } from "./IStoreErrors.sol"; import { IStoreHook } from "./IStoreHook.sol"; import { StoreSwitch } from "./StoreSwitch.sol"; import { Hook, HookLib } from "./Hook.sol"; import { BEFORE_SET_RECORD, AFTER_SET_RECORD, BEFORE_SPLICE_STATIC_DATA, AFTER_SPLICE_STATIC_DATA, BEFORE_SPLICE_DYNAMIC_DATA, AFTER_SPLICE_DYNAMIC_DATA, BEFORE_DELETE_RECORD, AFTER_DELETE_RECORD } from "./storeHookTypes.sol"; -import { ResourceId } from "./ResourceId.sol"; +import { ResourceId, ResourceIdLib } from "./ResourceId.sol"; import { RESOURCE_TABLE, RESOURCE_OFFCHAIN_TABLE } from "./storeResourceTypes.sol"; import { IStoreEvents } from "./IStoreEvents.sol"; @@ -78,10 +78,6 @@ library StoreCore { ResourceIds._setExists(ResourceIds._tableId, true); // Now we can register the rest of the core tables as regular tables. - ResourceNames.register(); - ResourceNames._setExists(Tables._tableId.getStoreName(), true); - ResourceNames._setExists(ResourceIds._tableId.getStoreName(), true); - StoreHooks.register(); } @@ -164,7 +160,7 @@ library StoreCore { string[] memory keyNames, string[] memory fieldNames ) internal { - // Verify the table ID is of type RESOURCE_TABLE + // Verify the table ID is of type RESOURCE_TABLE or RESOURCE_OFFCHAIN_TABLE if (tableId.getType() != RESOURCE_TABLE && tableId.getType() != RESOURCE_OFFCHAIN_TABLE) { revert IStoreErrors.Store_InvalidResourceType(RESOURCE_TABLE, tableId, string(abi.encodePacked(tableId))); } @@ -217,9 +213,20 @@ library StoreCore { if (ResourceIds._getExists(tableId)) { revert IStoreErrors.Store_TableAlreadyExists(tableId, string(abi.encodePacked(tableId))); } - // Verify there is no resource with this name yet - if (ResourceNames._getExists(tableId.getStoreName())) { - revert IStoreErrors.Store_TableAlreadyExists(tableId, string(abi.encodePacked(tableId))); + + // Verify that there is no table or offchain table with the same name + if (tableId.getType() == RESOURCE_TABLE) { + ResourceId tableIdOffchain = ResourceIdLib.encode(RESOURCE_OFFCHAIN_TABLE, tableId.getNameStore()); + + if (ResourceIds._getExists(tableIdOffchain)) { + revert IStoreErrors.Store_TableAlreadyExists(tableId, string(abi.encodePacked(tableId))); + } + } else if (tableId.getType() == RESOURCE_OFFCHAIN_TABLE) { + ResourceId tableIdOnchain = ResourceIdLib.encode(RESOURCE_TABLE, tableId.getNameStore()); + + if (ResourceIds._getExists(tableIdOnchain)) { + revert IStoreErrors.Store_TableAlreadyExists(tableId, string(abi.encodePacked(tableId))); + } } // Register the table metadata @@ -227,7 +234,6 @@ library StoreCore { // Register the table ID ResourceIds._setExists(tableId, true); - ResourceNames._setExists(tableId.getStoreName(), true); } /************************************************************************ diff --git a/packages/store/src/codegen/index.sol b/packages/store/src/codegen/index.sol index 80ad244524..062209e3db 100644 --- a/packages/store/src/codegen/index.sol +++ b/packages/store/src/codegen/index.sol @@ -6,5 +6,4 @@ pragma solidity >=0.8.24; import { StoreHooks } from "./tables/StoreHooks.sol"; import { Tables, TablesData } from "./tables/Tables.sol"; import { ResourceIds } from "./tables/ResourceIds.sol"; -import { ResourceNames } from "./tables/ResourceNames.sol"; import { Hooks } from "./tables/Hooks.sol"; diff --git a/packages/world-modules/gas-report.json b/packages/world-modules/gas-report.json index 8a0d17f9ce..6c5b7b74c4 100644 --- a/packages/world-modules/gas-report.json +++ b/packages/world-modules/gas-report.json @@ -3,7 +3,7 @@ "file": "test/CallWithSignatureModule.t.sol", "test": "testInstallRoot", "name": "install delegation module", - "gasUsed": 719957 + "gasUsed": 691108 }, { "file": "test/CallWithSignatureModule.t.sol", @@ -87,13 +87,13 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1518915 + "gasUsed": 1463243 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1518915 + "gasUsed": 1463243 }, { "file": "test/KeysInTableModule.t.sol", @@ -105,13 +105,13 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1518915 + "gasUsed": 1463243 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1518915 + "gasUsed": 1463243 }, { "file": "test/KeysInTableModule.t.sol", @@ -129,7 +129,7 @@ "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1518915 + "gasUsed": 1463243 }, { "file": "test/KeysInTableModule.t.sol", @@ -147,7 +147,7 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 747810 + "gasUsed": 718975 }, { "file": "test/KeysWithValueModule.t.sol", @@ -165,7 +165,7 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 747810 + "gasUsed": 718975 }, { "file": "test/KeysWithValueModule.t.sol", @@ -177,7 +177,7 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 747810 + "gasUsed": 718975 }, { "file": "test/KeysWithValueModule.t.sol", @@ -195,7 +195,7 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 747810 + "gasUsed": 718975 }, { "file": "test/KeysWithValueModule.t.sol", @@ -315,7 +315,7 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 747548 + "gasUsed": 718708 }, { "file": "test/UniqueEntityModule.t.sol", @@ -327,7 +327,7 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 718008 + "gasUsed": 689153 }, { "file": "test/UniqueEntityModule.t.sol", diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 2d9bbe76de..56bd635d80 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -63,7 +63,7 @@ "file": "test/Factories.t.sol", "test": "testWorldFactoryGas", "name": "deploy world via WorldFactory", - "gasUsed": 13657681 + "gasUsed": 12847506 }, { "file": "test/World.t.sol", @@ -129,7 +129,7 @@ "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 601725 + "gasUsed": 572890 }, { "file": "test/World.t.sol", @@ -249,7 +249,7 @@ "file": "test/WorldProxy.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 606735 + "gasUsed": 577900 }, { "file": "test/WorldProxy.t.sol", @@ -285,7 +285,7 @@ "file": "test/WorldProxyFactory.t.sol", "test": "testWorldProxyFactoryGas", "name": "deploy world via WorldProxyFactory", - "gasUsed": 9953221 + "gasUsed": 9143046 }, { "file": "test/WorldProxyFactory.t.sol", From c43d3daaad909dff827caac3219c455421629fad Mon Sep 17 00:00:00 2001 From: Fraser Scott Date: Thu, 25 Apr 2024 15:28:54 +0100 Subject: [PATCH 04/13] chore: docs --- docs/pages/store/reference/misc.mdx | 20 ++ .../src/codegen/tables/ResourceNames.sol | 211 ------------------ 2 files changed, 20 insertions(+), 211 deletions(-) delete mode 100644 packages/store/src/codegen/tables/ResourceNames.sol diff --git a/docs/pages/store/reference/misc.mdx b/docs/pages/store/reference/misc.mdx index c50a76c213..0d021142e3 100644 --- a/docs/pages/store/reference/misc.mdx +++ b/docs/pages/store/reference/misc.mdx @@ -1850,6 +1850,26 @@ function getType(ResourceId resourceId) internal pure returns (bytes2); | -------- | -------- | ------------------------------------- | | `` | `bytes2` | The extracted 2-byte type identifier. | +#### getNameStore + +Get the name from a resource ID. + +```solidity +function getNameStore(ResourceId resourceId) internal pure returns (bytes30); +``` + +**Parameters** + +| Name | Type | Description | +| ------------ | ------------ | ---------------- | +| `resourceId` | `ResourceId` | The resource ID. | + +**Returns** + +| Name | Type | Description | +| -------- | --------- | --------------- | +| `` | `bytes30` | A 30-byte name. | + ## ResourceIdLib [Git Source](https://github.com/latticexyz/mud/blob/main/packages/store/src/ResourceId.sol) diff --git a/packages/store/src/codegen/tables/ResourceNames.sol b/packages/store/src/codegen/tables/ResourceNames.sol deleted file mode 100644 index 7c1cebc7ad..0000000000 --- a/packages/store/src/codegen/tables/ResourceNames.sol +++ /dev/null @@ -1,211 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.24; - -/* Autogenerated file. Do not edit manually. */ - -// Import store internals -import { IStore } from "../../IStore.sol"; -import { StoreSwitch } from "../../StoreSwitch.sol"; -import { StoreCore } from "../../StoreCore.sol"; -import { Bytes } from "../../Bytes.sol"; -import { Memory } from "../../Memory.sol"; -import { SliceLib } from "../../Slice.sol"; -import { EncodeArray } from "../../tightcoder/EncodeArray.sol"; -import { FieldLayout } from "../../FieldLayout.sol"; -import { Schema } from "../../Schema.sol"; -import { EncodedLengths, EncodedLengthsLib } from "../../EncodedLengths.sol"; -import { ResourceId } from "../../ResourceId.sol"; - -library ResourceNames { - // Hex below is the result of `WorldResourceIdLib.encode({ namespace: "store", name: "ResourceNames", typeId: RESOURCE_TABLE });` - ResourceId constant _tableId = ResourceId.wrap(0x746273746f72650000000000000000005265736f757263654e616d6573000000); - - FieldLayout constant _fieldLayout = - FieldLayout.wrap(0x0001010001000000000000000000000000000000000000000000000000000000); - - // Hex-encoded key schema of (bytes30) - Schema constant _keySchema = Schema.wrap(0x001e01005d000000000000000000000000000000000000000000000000000000); - // Hex-encoded value schema of (bool) - Schema constant _valueSchema = Schema.wrap(0x0001010060000000000000000000000000000000000000000000000000000000); - - /** - * @notice Get the table's key field names. - * @return keyNames An array of strings with the names of key fields. - */ - function getKeyNames() internal pure returns (string[] memory keyNames) { - keyNames = new string[](1); - keyNames[0] = "name"; - } - - /** - * @notice Get the table's value field names. - * @return fieldNames An array of strings with the names of value fields. - */ - function getFieldNames() internal pure returns (string[] memory fieldNames) { - fieldNames = new string[](1); - fieldNames[0] = "exists"; - } - - /** - * @notice Register the table with its config. - */ - function register() internal { - StoreSwitch.registerTable(_tableId, _fieldLayout, _keySchema, _valueSchema, getKeyNames(), getFieldNames()); - } - - /** - * @notice Register the table with its config. - */ - function _register() internal { - StoreCore.registerTable(_tableId, _fieldLayout, _keySchema, _valueSchema, getKeyNames(), getFieldNames()); - } - - /** - * @notice Get exists. - */ - function getExists(bytes30 name) internal view returns (bool exists) { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(name); - - bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); - return (_toBool(uint8(bytes1(_blob)))); - } - - /** - * @notice Get exists. - */ - function _getExists(bytes30 name) internal view returns (bool exists) { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(name); - - bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); - return (_toBool(uint8(bytes1(_blob)))); - } - - /** - * @notice Get exists. - */ - function get(bytes30 name) internal view returns (bool exists) { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(name); - - bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); - return (_toBool(uint8(bytes1(_blob)))); - } - - /** - * @notice Get exists. - */ - function _get(bytes30 name) internal view returns (bool exists) { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(name); - - bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); - return (_toBool(uint8(bytes1(_blob)))); - } - - /** - * @notice Set exists. - */ - function setExists(bytes30 name, bool exists) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(name); - - StoreSwitch.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); - } - - /** - * @notice Set exists. - */ - function _setExists(bytes30 name, bool exists) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(name); - - StoreCore.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); - } - - /** - * @notice Set exists. - */ - function set(bytes30 name, bool exists) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(name); - - StoreSwitch.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); - } - - /** - * @notice Set exists. - */ - function _set(bytes30 name, bool exists) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(name); - - StoreCore.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((exists)), _fieldLayout); - } - - /** - * @notice Delete all data for given keys. - */ - function deleteRecord(bytes30 name) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(name); - - StoreSwitch.deleteRecord(_tableId, _keyTuple); - } - - /** - * @notice Delete all data for given keys. - */ - function _deleteRecord(bytes30 name) internal { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(name); - - StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); - } - - /** - * @notice Tightly pack static (fixed length) data using this table's schema. - * @return The static data, encoded into a sequence of bytes. - */ - function encodeStatic(bool exists) internal pure returns (bytes memory) { - return abi.encodePacked(exists); - } - - /** - * @notice Encode all of a record's fields. - * @return The static (fixed length) data, encoded into a sequence of bytes. - * @return The lengths of the dynamic fields (packed into a single bytes32 value). - * @return The dynamic (variable length) data, encoded into a sequence of bytes. - */ - function encode(bool exists) internal pure returns (bytes memory, EncodedLengths, bytes memory) { - bytes memory _staticData = encodeStatic(exists); - - EncodedLengths _encodedLengths; - bytes memory _dynamicData; - - return (_staticData, _encodedLengths, _dynamicData); - } - - /** - * @notice Encode keys as a bytes32 array using this table's field layout. - */ - function encodeKeyTuple(bytes30 name) internal pure returns (bytes32[] memory) { - bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = bytes32(name); - - return _keyTuple; - } -} - -/** - * @notice Cast a value to a bool. - * @dev Boolean values are encoded as uint8 (1 = true, 0 = false), but Solidity doesn't allow casting between uint8 and bool. - * @param value The uint8 value to convert. - * @return result The boolean value. - */ -function _toBool(uint8 value) pure returns (bool result) { - assembly { - result := value - } -} From b5168ff3b04ad3febcfbcbb418625f3e4ba6ecd4 Mon Sep 17 00:00:00 2001 From: Fraser Scott Date: Thu, 25 Apr 2024 15:48:44 +0100 Subject: [PATCH 05/13] refactor: just check onchain and offchain --- packages/store/gas-report.json | 102 ++++++++++++------------- packages/store/src/StoreCore.sol | 21 +---- packages/world-modules/gas-report.json | 24 +++--- packages/world/gas-report.json | 8 +- 4 files changed, 71 insertions(+), 84 deletions(-) diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index b8f83a8666..b3b2ab23e7 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -21,7 +21,7 @@ "file": "test/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 56133 + "gasUsed": 56118 }, { "file": "test/Callbacks.t.sol", @@ -33,7 +33,7 @@ "file": "test/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 32417 + "gasUsed": 32402 }, { "file": "test/EncodedLengths.t.sol", @@ -357,7 +357,7 @@ "file": "test/KeyEncoding.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register KeyEncoding table", - "gasUsed": 721046 + "gasUsed": 721008 }, { "file": "test/Mixed.t.sol", @@ -369,19 +369,19 @@ "file": "test/Mixed.t.sol", "test": "testDeleteExternalCold", "name": "delete record from Mixed (external, cold)", - "gasUsed": 23530 + "gasUsed": 23515 }, { "file": "test/Mixed.t.sol", "test": "testDeleteInternalCold", "name": "delete record from Mixed (internal, cold)", - "gasUsed": 18739 + "gasUsed": 18724 }, { "file": "test/Mixed.t.sol", "test": "testSetGetDeleteExternal", "name": "set record in Mixed (external, cold)", - "gasUsed": 107680 + "gasUsed": 107665 }, { "file": "test/Mixed.t.sol", @@ -393,13 +393,13 @@ "file": "test/Mixed.t.sol", "test": "testSetGetDeleteExternal", "name": "delete record from Mixed (external, warm)", - "gasUsed": 7841 + "gasUsed": 7826 }, { "file": "test/Mixed.t.sol", "test": "testSetGetDeleteInternal", "name": "set record in Mixed (internal, cold)", - "gasUsed": 102846 + "gasUsed": 102831 }, { "file": "test/Mixed.t.sol", @@ -411,7 +411,7 @@ "file": "test/Mixed.t.sol", "test": "testSetGetDeleteInternal", "name": "delete record from Mixed (internal, warm)", - "gasUsed": 7048 + "gasUsed": 7033 }, { "file": "test/ResourceId.t.sol", @@ -627,25 +627,25 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 18122 + "gasUsed": 18107 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 12129 + "gasUsed": 12114 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 15891 + "gasUsed": 15876 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 11898 + "gasUsed": 11883 }, { "file": "test/StoreCoreGas.t.sol", @@ -675,13 +675,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 7388 + "gasUsed": 7373 }, { "file": "test/StoreCoreGas.t.sol", "test": "testDeleteDataOffchainTable", "name": "StoreCore: delete record in offchain table", - "gasUsed": 28240 + "gasUsed": 28225 }, { "file": "test/StoreCoreGas.t.sol", @@ -711,67 +711,67 @@ "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 56619 + "gasUsed": 56589 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 98316 + "gasUsed": 98286 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 52934 + "gasUsed": 52904 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 47519 + "gasUsed": 47489 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 56619 + "gasUsed": 56589 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 191673 + "gasUsed": 191643 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 60404 + "gasUsed": 60374 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 49296 + "gasUsed": 49266 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToDynamicField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 9554 + "gasUsed": 9539 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToDynamicField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 32226 + "gasUsed": 32211 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 651094 + "gasUsed": 651056 }, { "file": "test/StoreCoreGas.t.sol", @@ -795,7 +795,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 101882 + "gasUsed": 101867 }, { "file": "test/StoreCoreGas.t.sol", @@ -837,7 +837,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 31041 + "gasUsed": 31026 }, { "file": "test/StoreCoreGas.t.sol", @@ -849,7 +849,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 29624 + "gasUsed": 29609 }, { "file": "test/StoreCoreGas.t.sol", @@ -861,7 +861,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 54037 + "gasUsed": 54022 }, { "file": "test/StoreCoreGas.t.sol", @@ -873,7 +873,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 32262 + "gasUsed": 32247 }, { "file": "test/StoreCoreGas.t.sol", @@ -885,7 +885,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 32157 + "gasUsed": 32142 }, { "file": "test/StoreCoreGas.t.sol", @@ -897,7 +897,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 54665 + "gasUsed": 54650 }, { "file": "test/StoreCoreGas.t.sol", @@ -909,19 +909,19 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetDataOffchainTable", "name": "StoreCore: set record in offchain table", - "gasUsed": 32532 + "gasUsed": 32517 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInDynamicField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 8914 + "gasUsed": 8899 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInDynamicField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 9357 + "gasUsed": 9342 }, { "file": "test/StoreHook.t.sol", @@ -951,13 +951,13 @@ "file": "test/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 58127 + "gasUsed": 58112 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 58127 + "gasUsed": 58112 }, { "file": "test/StoreHooks.t.sol", @@ -969,55 +969,55 @@ "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 12506 + "gasUsed": 12491 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 9810 + "gasUsed": 9795 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 10522 + "gasUsed": 10507 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 29756 + "gasUsed": 29741 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: delete record (warm)", - "gasUsed": 9567 + "gasUsed": 9552 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 30270 + "gasUsed": 30255 }, { "file": "test/StoreHooks.t.sol", "test": "testThreeSlots", "name": "StoreHooks: set field with three elements (cold)", - "gasUsed": 80818 + "gasUsed": 80803 }, { "file": "test/StoreHooks.t.sol", "test": "testTwoSlots", "name": "StoreHooks: set field with two elements (cold)", - "gasUsed": 80730 + "gasUsed": 80715 }, { "file": "test/StoreHooksColdLoad.t.sol", "test": "testDelete", "name": "StoreHooks: delete record (cold)", - "gasUsed": 18439 + "gasUsed": 18424 }, { "file": "test/StoreHooksColdLoad.t.sol", @@ -1041,13 +1041,13 @@ "file": "test/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 18246 + "gasUsed": 18231 }, { "file": "test/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 20209 + "gasUsed": 20194 }, { "file": "test/StoreSwitch.t.sol", @@ -1113,13 +1113,13 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 447101 + "gasUsed": 447063 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 32839 + "gasUsed": 32824 }, { "file": "test/Vector2.t.sol", diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index 47d79b271a..ed8a683bbb 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -209,24 +209,11 @@ library StoreCore { } } - // Verify there is no resource with this ID yet - if (ResourceIds._getExists(tableId)) { - revert IStoreErrors.Store_TableAlreadyExists(tableId, string(abi.encodePacked(tableId))); - } - // Verify that there is no table or offchain table with the same name - if (tableId.getType() == RESOURCE_TABLE) { - ResourceId tableIdOffchain = ResourceIdLib.encode(RESOURCE_OFFCHAIN_TABLE, tableId.getNameStore()); - - if (ResourceIds._getExists(tableIdOffchain)) { - revert IStoreErrors.Store_TableAlreadyExists(tableId, string(abi.encodePacked(tableId))); - } - } else if (tableId.getType() == RESOURCE_OFFCHAIN_TABLE) { - ResourceId tableIdOnchain = ResourceIdLib.encode(RESOURCE_TABLE, tableId.getNameStore()); - - if (ResourceIds._getExists(tableIdOnchain)) { - revert IStoreErrors.Store_TableAlreadyExists(tableId, string(abi.encodePacked(tableId))); - } + ResourceId onchainTableId = ResourceIdLib.encode(RESOURCE_TABLE, tableId.getNameStore()); + ResourceId offchainTableId = ResourceIdLib.encode(RESOURCE_OFFCHAIN_TABLE, tableId.getNameStore()); + if (ResourceIds._getExists(onchainTableId) || ResourceIds._getExists(offchainTableId)) { + revert IStoreErrors.Store_TableAlreadyExists(tableId, string(abi.encodePacked(tableId))); } // Register the table metadata diff --git a/packages/world-modules/gas-report.json b/packages/world-modules/gas-report.json index 6c5b7b74c4..896b0f03d2 100644 --- a/packages/world-modules/gas-report.json +++ b/packages/world-modules/gas-report.json @@ -3,7 +3,7 @@ "file": "test/CallWithSignatureModule.t.sol", "test": "testInstallRoot", "name": "install delegation module", - "gasUsed": 691108 + "gasUsed": 691133 }, { "file": "test/CallWithSignatureModule.t.sol", @@ -87,13 +87,13 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1463243 + "gasUsed": 1463317 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1463243 + "gasUsed": 1463317 }, { "file": "test/KeysInTableModule.t.sol", @@ -105,13 +105,13 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1463243 + "gasUsed": 1463317 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1463243 + "gasUsed": 1463317 }, { "file": "test/KeysInTableModule.t.sol", @@ -129,7 +129,7 @@ "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1463243 + "gasUsed": 1463317 }, { "file": "test/KeysInTableModule.t.sol", @@ -147,7 +147,7 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 718975 + "gasUsed": 719012 }, { "file": "test/KeysWithValueModule.t.sol", @@ -165,7 +165,7 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 718975 + "gasUsed": 719012 }, { "file": "test/KeysWithValueModule.t.sol", @@ -177,7 +177,7 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 718975 + "gasUsed": 719012 }, { "file": "test/KeysWithValueModule.t.sol", @@ -195,7 +195,7 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 718975 + "gasUsed": 719012 }, { "file": "test/KeysWithValueModule.t.sol", @@ -315,7 +315,7 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 718708 + "gasUsed": 718745 }, { "file": "test/UniqueEntityModule.t.sol", @@ -327,7 +327,7 @@ "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 689153 + "gasUsed": 689190 }, { "file": "test/UniqueEntityModule.t.sol", diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 56bd635d80..d2da0ab8d7 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -63,7 +63,7 @@ "file": "test/Factories.t.sol", "test": "testWorldFactoryGas", "name": "deploy world via WorldFactory", - "gasUsed": 12847506 + "gasUsed": 12847807 }, { "file": "test/World.t.sol", @@ -129,7 +129,7 @@ "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 572890 + "gasUsed": 572927 }, { "file": "test/World.t.sol", @@ -249,7 +249,7 @@ "file": "test/WorldProxy.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 577900 + "gasUsed": 577937 }, { "file": "test/WorldProxy.t.sol", @@ -285,7 +285,7 @@ "file": "test/WorldProxyFactory.t.sol", "test": "testWorldProxyFactoryGas", "name": "deploy world via WorldProxyFactory", - "gasUsed": 9143046 + "gasUsed": 9143347 }, { "file": "test/WorldProxyFactory.t.sol", From b5b6a04d0a3764697e3a4ffbcaf9be861935c509 Mon Sep 17 00:00:00 2001 From: Fraser Scott Date: Thu, 25 Apr 2024 15:50:57 +0100 Subject: [PATCH 06/13] refactor: getResourceName --- docs/pages/store/reference/misc.mdx | 4 ++-- packages/store/src/ResourceId.sol | 2 +- packages/store/src/StoreCore.sol | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/pages/store/reference/misc.mdx b/docs/pages/store/reference/misc.mdx index 0d021142e3..6d39d846aa 100644 --- a/docs/pages/store/reference/misc.mdx +++ b/docs/pages/store/reference/misc.mdx @@ -1850,12 +1850,12 @@ function getType(ResourceId resourceId) internal pure returns (bytes2); | -------- | -------- | ------------------------------------- | | `` | `bytes2` | The extracted 2-byte type identifier. | -#### getNameStore +#### getResourceName Get the name from a resource ID. ```solidity -function getNameStore(ResourceId resourceId) internal pure returns (bytes30); +function getResourceName(ResourceId resourceId) internal pure returns (bytes30); ``` **Parameters** diff --git a/packages/store/src/ResourceId.sol b/packages/store/src/ResourceId.sol index a332b6ee68..03cf8c7c0a 100644 --- a/packages/store/src/ResourceId.sol +++ b/packages/store/src/ResourceId.sol @@ -51,7 +51,7 @@ library ResourceIdInstance { * @param resourceId The resource ID. * @return A 30-byte name. */ - function getNameStore(ResourceId resourceId) internal pure returns (bytes30) { + function getResourceName(ResourceId resourceId) internal pure returns (bytes30) { return bytes30(ResourceId.unwrap(resourceId) << (TYPE_BITS)); } } diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index ed8a683bbb..696bb399f6 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -210,8 +210,8 @@ library StoreCore { } // Verify that there is no table or offchain table with the same name - ResourceId onchainTableId = ResourceIdLib.encode(RESOURCE_TABLE, tableId.getNameStore()); - ResourceId offchainTableId = ResourceIdLib.encode(RESOURCE_OFFCHAIN_TABLE, tableId.getNameStore()); + ResourceId onchainTableId = ResourceIdLib.encode(RESOURCE_TABLE, tableId.getResourceName()); + ResourceId offchainTableId = ResourceIdLib.encode(RESOURCE_OFFCHAIN_TABLE, tableId.getResourceName()); if (ResourceIds._getExists(onchainTableId) || ResourceIds._getExists(offchainTableId)) { revert IStoreErrors.Store_TableAlreadyExists(tableId, string(abi.encodePacked(tableId))); } From 0d54fb4cc9f4b171cf415572ce81f4aeaf73245a Mon Sep 17 00:00:00 2001 From: Fraser Scott Date: Thu, 25 Apr 2024 15:58:15 +0100 Subject: [PATCH 07/13] chore: changeset --- .changeset/strong-lobsters-shake.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/strong-lobsters-shake.md diff --git a/.changeset/strong-lobsters-shake.md b/.changeset/strong-lobsters-shake.md new file mode 100644 index 0000000000..59cd4558e2 --- /dev/null +++ b/.changeset/strong-lobsters-shake.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/store": patch +--- + +Added a check to `registerTable` that namespace and name are unique, which prevents registering both an offchain and onchain table with the same namespace and name, and makes indexing with decoded tables easier. From 0c1b22ba1ebeac079077607fc640de319a8db0a5 Mon Sep 17 00:00:00 2001 From: Fraser Scott Date: Thu, 25 Apr 2024 15:59:17 +0100 Subject: [PATCH 08/13] chore: tweak changeset --- .changeset/strong-lobsters-shake.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/strong-lobsters-shake.md b/.changeset/strong-lobsters-shake.md index 59cd4558e2..036253ea37 100644 --- a/.changeset/strong-lobsters-shake.md +++ b/.changeset/strong-lobsters-shake.md @@ -2,4 +2,4 @@ "@latticexyz/store": patch --- -Added a check to `registerTable` that namespace and name are unique, which prevents registering both an offchain and onchain table with the same namespace and name, and makes indexing with decoded tables easier. +Added a check to `registerTable` that prevents registering both an offchain and onchain table with the same namespace and name, making indexing with decoded tables easier. From 0af07a165e0e9d19710ca559e8102888d2a71c30 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 25 Apr 2024 08:24:52 -0700 Subject: [PATCH 09/13] Update .changeset/strong-lobsters-shake.md --- .changeset/strong-lobsters-shake.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/strong-lobsters-shake.md b/.changeset/strong-lobsters-shake.md index 036253ea37..3f657a2adb 100644 --- a/.changeset/strong-lobsters-shake.md +++ b/.changeset/strong-lobsters-shake.md @@ -2,4 +2,4 @@ "@latticexyz/store": patch --- -Added a check to `registerTable` that prevents registering both an offchain and onchain table with the same namespace and name, making indexing with decoded tables easier. +Added a check to `registerTable` that prevents registering both an offchain and onchain table with the same name, making it easier to use human-readable names in indexers. From 40ba6ee404170410c4e6e05005040725e2fb6b0c Mon Sep 17 00:00:00 2001 From: Fraser Scott Date: Thu, 25 Apr 2024 16:27:18 +0100 Subject: [PATCH 10/13] chore: bump protocol versions --- packages/store/src/version.sol | 2 +- packages/world/src/version.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/store/src/version.sol b/packages/store/src/version.sol index 3e0a984e7a..3f0b1abcc6 100644 --- a/packages/store/src/version.sol +++ b/packages/store/src/version.sol @@ -8,4 +8,4 @@ pragma solidity >=0.8.24; */ /// @dev Identifier for the current Store protocol version. -bytes32 constant STORE_VERSION = "2.0.1"; +bytes32 constant STORE_VERSION = "2.0.2"; diff --git a/packages/world/src/version.sol b/packages/world/src/version.sol index 15315b6673..c09c418bc9 100644 --- a/packages/world/src/version.sol +++ b/packages/world/src/version.sol @@ -8,4 +8,4 @@ pragma solidity >=0.8.24; */ /// @dev Identifier for the current World protocol version. -bytes32 constant WORLD_VERSION = "2.0.1"; +bytes32 constant WORLD_VERSION = "2.0.2"; From 4d44412346d4bbb4e8f507aa100a5e5f88260b60 Mon Sep 17 00:00:00 2001 From: Fraser Scott Date: Thu, 25 Apr 2024 16:31:36 +0100 Subject: [PATCH 11/13] chore: snap --- .../store/ts/protocol-snapshots/2.0.2.snap | 57 ++++++++++ packages/store/ts/protocolVersions.ts | 2 + .../world/ts/protocol-snapshots/2.0.2.snap | 102 ++++++++++++++++++ packages/world/ts/protocolVersions.ts | 2 + 4 files changed, 163 insertions(+) create mode 100644 packages/store/ts/protocol-snapshots/2.0.2.snap create mode 100644 packages/world/ts/protocol-snapshots/2.0.2.snap diff --git a/packages/store/ts/protocol-snapshots/2.0.2.snap b/packages/store/ts/protocol-snapshots/2.0.2.snap new file mode 100644 index 0000000000..21c6ecc745 --- /dev/null +++ b/packages/store/ts/protocol-snapshots/2.0.2.snap @@ -0,0 +1,57 @@ +[ + "error EncodedLengths_InvalidLength(uint256 length)", + "error FieldLayout_Empty()", + "error FieldLayout_InvalidStaticDataLength(uint256 staticDataLength, uint256 computedStaticDataLength)", + "error FieldLayout_StaticLengthDoesNotFitInAWord(uint256 index)", + "error FieldLayout_StaticLengthIsNotZero(uint256 index)", + "error FieldLayout_StaticLengthIsZero(uint256 index)", + "error FieldLayout_TooManyDynamicFields(uint256 numFields, uint256 maxFields)", + "error FieldLayout_TooManyFields(uint256 numFields, uint256 maxFields)", + "error Schema_InvalidLength(uint256 length)", + "error Schema_StaticTypeAfterDynamicType()", + "error Slice_OutOfBounds(bytes data, uint256 start, uint256 end)", + "error Store_IndexOutOfBounds(uint256 length, uint256 accessedIndex)", + "error Store_InvalidBounds(uint256 start, uint256 end)", + "error Store_InvalidFieldNamesLength(uint256 expected, uint256 received)", + "error Store_InvalidKeyNamesLength(uint256 expected, uint256 received)", + "error Store_InvalidResourceType(bytes2 expected, bytes32 resourceId, string resourceIdString)", + "error Store_InvalidSplice(uint40 startWithinField, uint40 deleteCount, uint40 fieldLength)", + "error Store_InvalidStaticDataLength(uint256 expected, uint256 received)", + "error Store_InvalidValueSchemaDynamicLength(uint256 expected, uint256 received)", + "error Store_InvalidValueSchemaLength(uint256 expected, uint256 received)", + "error Store_InvalidValueSchemaStaticLength(uint256 expected, uint256 received)", + "error Store_TableAlreadyExists(bytes32 tableId, string tableIdString)", + "error Store_TableNotFound(bytes32 tableId, string tableIdString)", + "event HelloStore(bytes32 indexed storeVersion)", + "event Store_DeleteRecord(bytes32 indexed tableId, bytes32[] keyTuple)", + "event Store_SetRecord(bytes32 indexed tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData)", + "event Store_SpliceDynamicData(bytes32 indexed tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex, uint48 start, uint40 deleteCount, bytes32 encodedLengths, bytes data)", + "event Store_SpliceStaticData(bytes32 indexed tableId, bytes32[] keyTuple, uint48 start, bytes data)", + "function deleteRecord(bytes32 tableId, bytes32[] keyTuple)", + "function getDynamicField(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex) view returns (bytes)", + "function getDynamicFieldLength(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex) view returns (uint256)", + "function getDynamicFieldSlice(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex, uint256 start, uint256 end) view returns (bytes data)", + "function getField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes32 fieldLayout) view returns (bytes data)", + "function getField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex) view returns (bytes data)", + "function getFieldLayout(bytes32 tableId) view returns (bytes32 fieldLayout)", + "function getFieldLength(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes32 fieldLayout) view returns (uint256)", + "function getFieldLength(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex) view returns (uint256)", + "function getKeySchema(bytes32 tableId) view returns (bytes32 keySchema)", + "function getRecord(bytes32 tableId, bytes32[] keyTuple, bytes32 fieldLayout) view returns (bytes staticData, bytes32 encodedLengths, bytes dynamicData)", + "function getRecord(bytes32 tableId, bytes32[] keyTuple) view returns (bytes staticData, bytes32 encodedLengths, bytes dynamicData)", + "function getStaticField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes32 fieldLayout) view returns (bytes32)", + "function getValueSchema(bytes32 tableId) view returns (bytes32 valueSchema)", + "function popFromDynamicField(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex, uint256 byteLengthToPop)", + "function pushToDynamicField(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex, bytes dataToPush)", + "function registerStoreHook(bytes32 tableId, address hookAddress, uint8 enabledHooksBitmap)", + "function registerTable(bytes32 tableId, bytes32 fieldLayout, bytes32 keySchema, bytes32 valueSchema, string[] keyNames, string[] fieldNames)", + "function setDynamicField(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex, bytes data)", + "function setField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes data, bytes32 fieldLayout)", + "function setField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes data)", + "function setRecord(bytes32 tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData)", + "function setStaticField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes data, bytes32 fieldLayout)", + "function spliceDynamicData(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, uint40 deleteCount, bytes data)", + "function spliceStaticData(bytes32 tableId, bytes32[] keyTuple, uint48 start, bytes data)", + "function storeVersion() view returns (bytes32 version)", + "function unregisterStoreHook(bytes32 tableId, address hookAddress)", +] \ No newline at end of file diff --git a/packages/store/ts/protocolVersions.ts b/packages/store/ts/protocolVersions.ts index f99100a48a..b91dcbbbc2 100644 --- a/packages/store/ts/protocolVersions.ts +++ b/packages/store/ts/protocolVersions.ts @@ -1,5 +1,7 @@ // History of protocol versions and a short description of what changed in each. export const protocolVersions = { + "2.0.2": + "Patched `StoreCore.registerTable` to prevent registering both an offchain and onchain table with the same name.", "2.0.1": "Patched `StoreRead.getDynamicFieldLength` to use the correct method to read the dynamic field length.", "2.0.0": "Initial v2 release. See mud.dev/changelog for the full list of changes from v1.", }; diff --git a/packages/world/ts/protocol-snapshots/2.0.2.snap b/packages/world/ts/protocol-snapshots/2.0.2.snap new file mode 100644 index 0000000000..aed3400889 --- /dev/null +++ b/packages/world/ts/protocol-snapshots/2.0.2.snap @@ -0,0 +1,102 @@ +[ + "error EncodedLengths_InvalidLength(uint256 length)", + "error FieldLayout_Empty()", + "error FieldLayout_InvalidStaticDataLength(uint256 staticDataLength, uint256 computedStaticDataLength)", + "error FieldLayout_StaticLengthDoesNotFitInAWord(uint256 index)", + "error FieldLayout_StaticLengthIsNotZero(uint256 index)", + "error FieldLayout_StaticLengthIsZero(uint256 index)", + "error FieldLayout_TooManyDynamicFields(uint256 numFields, uint256 maxFields)", + "error FieldLayout_TooManyFields(uint256 numFields, uint256 maxFields)", + "error Module_AlreadyInstalled()", + "error Module_MissingDependency(address dependency)", + "error Module_NonRootInstallNotSupported()", + "error Module_RootInstallNotSupported()", + "error Schema_InvalidLength(uint256 length)", + "error Schema_StaticTypeAfterDynamicType()", + "error Slice_OutOfBounds(bytes data, uint256 start, uint256 end)", + "error Store_IndexOutOfBounds(uint256 length, uint256 accessedIndex)", + "error Store_InvalidBounds(uint256 start, uint256 end)", + "error Store_InvalidFieldNamesLength(uint256 expected, uint256 received)", + "error Store_InvalidKeyNamesLength(uint256 expected, uint256 received)", + "error Store_InvalidResourceType(bytes2 expected, bytes32 resourceId, string resourceIdString)", + "error Store_InvalidSplice(uint40 startWithinField, uint40 deleteCount, uint40 fieldLength)", + "error Store_InvalidStaticDataLength(uint256 expected, uint256 received)", + "error Store_InvalidValueSchemaDynamicLength(uint256 expected, uint256 received)", + "error Store_InvalidValueSchemaLength(uint256 expected, uint256 received)", + "error Store_InvalidValueSchemaStaticLength(uint256 expected, uint256 received)", + "error Store_TableAlreadyExists(bytes32 tableId, string tableIdString)", + "error Store_TableNotFound(bytes32 tableId, string tableIdString)", + "error World_AccessDenied(string resource, address caller)", + "error World_AlreadyInitialized()", + "error World_CallbackNotAllowed(bytes4 functionSelector)", + "error World_DelegationNotFound(address delegator, address delegatee)", + "error World_FunctionSelectorAlreadyExists(bytes4 functionSelector)", + "error World_FunctionSelectorNotFound(bytes4 functionSelector)", + "error World_InsufficientBalance(uint256 balance, uint256 amount)", + "error World_InterfaceNotSupported(address contractAddress, bytes4 interfaceId)", + "error World_InvalidNamespace(bytes14 namespace)", + "error World_InvalidResourceId(bytes32 resourceId, string resourceIdString)", + "error World_InvalidResourceType(bytes2 expected, bytes32 resourceId, string resourceIdString)", + "error World_ResourceAlreadyExists(bytes32 resourceId, string resourceIdString)", + "error World_ResourceNotFound(bytes32 resourceId, string resourceIdString)", + "error World_SystemAlreadyExists(address system)", + "error World_UnlimitedDelegationNotAllowed()", + "event HelloStore(bytes32 indexed storeVersion)", + "event HelloWorld(bytes32 indexed worldVersion)", + "event Store_DeleteRecord(bytes32 indexed tableId, bytes32[] keyTuple)", + "event Store_SetRecord(bytes32 indexed tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData)", + "event Store_SpliceDynamicData(bytes32 indexed tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex, uint48 start, uint40 deleteCount, bytes32 encodedLengths, bytes data)", + "event Store_SpliceStaticData(bytes32 indexed tableId, bytes32[] keyTuple, uint48 start, bytes data)", + "function batchCall((bytes32 systemId, bytes callData)[] systemCalls) returns (bytes[] returnDatas)", + "function batchCallFrom((address from, bytes32 systemId, bytes callData)[] systemCalls) returns (bytes[] returnDatas)", + "function call(bytes32 systemId, bytes callData) payable returns (bytes)", + "function callFrom(address delegator, bytes32 systemId, bytes callData) payable returns (bytes)", + "function creator() view returns (address)", + "function deleteRecord(bytes32 tableId, bytes32[] keyTuple)", + "function getDynamicField(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex) view returns (bytes)", + "function getDynamicFieldLength(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex) view returns (uint256)", + "function getDynamicFieldSlice(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex, uint256 start, uint256 end) view returns (bytes data)", + "function getField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes32 fieldLayout) view returns (bytes data)", + "function getField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex) view returns (bytes data)", + "function getFieldLayout(bytes32 tableId) view returns (bytes32 fieldLayout)", + "function getFieldLength(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes32 fieldLayout) view returns (uint256)", + "function getFieldLength(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex) view returns (uint256)", + "function getKeySchema(bytes32 tableId) view returns (bytes32 keySchema)", + "function getRecord(bytes32 tableId, bytes32[] keyTuple, bytes32 fieldLayout) view returns (bytes staticData, bytes32 encodedLengths, bytes dynamicData)", + "function getRecord(bytes32 tableId, bytes32[] keyTuple) view returns (bytes staticData, bytes32 encodedLengths, bytes dynamicData)", + "function getStaticField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes32 fieldLayout) view returns (bytes32)", + "function getValueSchema(bytes32 tableId) view returns (bytes32 valueSchema)", + "function grantAccess(bytes32 resourceId, address grantee)", + "function initialize(address initModule)", + "function installModule(address module, bytes encodedArgs)", + "function installRootModule(address module, bytes encodedArgs)", + "function popFromDynamicField(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex, uint256 byteLengthToPop)", + "function pushToDynamicField(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex, bytes dataToPush)", + "function registerDelegation(address delegatee, bytes32 delegationControlId, bytes initCallData)", + "function registerFunctionSelector(bytes32 systemId, string systemFunctionSignature) returns (bytes4 worldFunctionSelector)", + "function registerNamespace(bytes32 namespaceId)", + "function registerNamespaceDelegation(bytes32 namespaceId, bytes32 delegationControlId, bytes initCallData)", + "function registerRootFunctionSelector(bytes32 systemId, string worldFunctionSignature, string systemFunctionSignature) returns (bytes4 worldFunctionSelector)", + "function registerStoreHook(bytes32 tableId, address hookAddress, uint8 enabledHooksBitmap)", + "function registerSystem(bytes32 systemId, address system, bool publicAccess)", + "function registerSystemHook(bytes32 systemId, address hookAddress, uint8 enabledHooksBitmap)", + "function registerTable(bytes32 tableId, bytes32 fieldLayout, bytes32 keySchema, bytes32 valueSchema, string[] keyNames, string[] fieldNames)", + "function renounceOwnership(bytes32 namespaceId)", + "function revokeAccess(bytes32 resourceId, address grantee)", + "function setDynamicField(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex, bytes data)", + "function setField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes data, bytes32 fieldLayout)", + "function setField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes data)", + "function setRecord(bytes32 tableId, bytes32[] keyTuple, bytes staticData, bytes32 encodedLengths, bytes dynamicData)", + "function setStaticField(bytes32 tableId, bytes32[] keyTuple, uint8 fieldIndex, bytes data, bytes32 fieldLayout)", + "function spliceDynamicData(bytes32 tableId, bytes32[] keyTuple, uint8 dynamicFieldIndex, uint40 startWithinField, uint40 deleteCount, bytes data)", + "function spliceStaticData(bytes32 tableId, bytes32[] keyTuple, uint48 start, bytes data)", + "function storeVersion() view returns (bytes32 version)", + "function transferBalanceToAddress(bytes32 fromNamespaceId, address toAddress, uint256 amount)", + "function transferBalanceToNamespace(bytes32 fromNamespaceId, bytes32 toNamespaceId, uint256 amount)", + "function transferOwnership(bytes32 namespaceId, address newOwner)", + "function unregisterDelegation(address delegatee)", + "function unregisterNamespaceDelegation(bytes32 namespaceId)", + "function unregisterStoreHook(bytes32 tableId, address hookAddress)", + "function unregisterSystemHook(bytes32 systemId, address hookAddress)", + "function worldVersion() view returns (bytes32)", +] \ No newline at end of file diff --git a/packages/world/ts/protocolVersions.ts b/packages/world/ts/protocolVersions.ts index f99100a48a..b91dcbbbc2 100644 --- a/packages/world/ts/protocolVersions.ts +++ b/packages/world/ts/protocolVersions.ts @@ -1,5 +1,7 @@ // History of protocol versions and a short description of what changed in each. export const protocolVersions = { + "2.0.2": + "Patched `StoreCore.registerTable` to prevent registering both an offchain and onchain table with the same name.", "2.0.1": "Patched `StoreRead.getDynamicFieldLength` to use the correct method to read the dynamic field length.", "2.0.0": "Initial v2 release. See mud.dev/changelog for the full list of changes from v1.", }; From 966df87e2fd7ea49e5851af44977a7f61f5b158e Mon Sep 17 00:00:00 2001 From: Fraser Scott Date: Thu, 25 Apr 2024 16:34:08 +0100 Subject: [PATCH 12/13] chore: supported versions --- packages/cli/src/deploy/common.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/deploy/common.ts b/packages/cli/src/deploy/common.ts index a13035cc6e..da4a2f29c1 100644 --- a/packages/cli/src/deploy/common.ts +++ b/packages/cli/src/deploy/common.ts @@ -25,8 +25,8 @@ export const worldDeployEvents = [helloStoreEvent, helloWorldEvent] as const; export const worldAbi = [...IBaseWorldAbi, ...IModuleAbi] as const; // Ideally, this should be an append-only list. Before adding more versions here, be sure to add backwards-compatible support for old Store/World versions. -export const supportedStoreVersions = ["2.0.0", "2.0.1"]; -export const supportedWorldVersions = ["2.0.0", "2.0.1"]; +export const supportedStoreVersions = ["2.0.0", "2.0.1", "2.0.2"]; +export const supportedWorldVersions = ["2.0.0", "2.0.1", "2.0.2"]; // TODO: extend this to include factory+deployer address? so we can reuse the deployer for a world? export type WorldDeploy = { From 746f0b54b1937abab11c8df7b168f37d56dcf410 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 25 Apr 2024 18:42:49 +0100 Subject: [PATCH 13/13] generate docs --- docs/pages/store/reference/misc.mdx | 2 +- docs/pages/world/reference/misc.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/store/reference/misc.mdx b/docs/pages/store/reference/misc.mdx index 6d39d846aa..abae9a77b9 100644 --- a/docs/pages/store/reference/misc.mdx +++ b/docs/pages/store/reference/misc.mdx @@ -2708,5 +2708,5 @@ Contains a constant representing the version of the Store protocol. _Identifier for the current Store protocol version._ ```solidity -bytes32 constant STORE_VERSION = "2.0.1"; +bytes32 constant STORE_VERSION = "2.0.2"; ``` diff --git a/docs/pages/world/reference/misc.mdx b/docs/pages/world/reference/misc.mdx index f243fec51a..be7eea5f25 100644 --- a/docs/pages/world/reference/misc.mdx +++ b/docs/pages/world/reference/misc.mdx @@ -104,5 +104,5 @@ Contains a constant representing the version of the World protocol. _Identifier for the current World protocol version._ ```solidity -bytes32 constant WORLD_VERSION = "2.0.1"; +bytes32 constant WORLD_VERSION = "2.0.2"; ```