From b81f2c95ed666462671b09e9b1230ef3539ce773 Mon Sep 17 00:00:00 2001 From: Boffee Date: Fri, 15 Sep 2023 15:40:12 -0500 Subject: [PATCH 1/4] feat(store): optimize storage location hash --- packages/store/gas-report.json | 162 +++++++++++++++---------------- packages/store/src/StoreCore.sol | 8 +- packages/world/gas-report.json | 122 +++++++++++------------ 3 files changed, 147 insertions(+), 145 deletions(-) diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 06772c450b..314f78294b 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -309,7 +309,7 @@ "file": "test/KeyEncoding.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register KeyEncoding table", - "gasUsed": 697905 + "gasUsed": 696963 }, { "file": "test/Mixed.t.sol", @@ -321,19 +321,19 @@ "file": "test/Mixed.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Mixed table", - "gasUsed": 560027 + "gasUsed": 559124 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "set record in Mixed", - "gasUsed": 108640 + "gasUsed": 107832 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "get record from Mixed", - "gasUsed": 9640 + "gasUsed": 9118 }, { "file": "test/PackedCounter.t.sol", @@ -519,217 +519,217 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (cold, 1 slot)", - "gasUsed": 8425 + "gasUsed": 8363 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (warm, 1 slot)", - "gasUsed": 2493 + "gasUsed": 2431 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (semi-cold, 1 slot)", - "gasUsed": 4498 + "gasUsed": 4434 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (warm, 2 slots)", - "gasUsed": 4725 + "gasUsed": 4660 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetSecondFieldLength", "name": "get field length (cold, 1 slot)", - "gasUsed": 7966 + "gasUsed": 7739 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetSecondFieldLength", "name": "get field length (warm, 1 slot)", - "gasUsed": 1961 + "gasUsed": 1735 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetThirdFieldLength", "name": "get field length (warm due to , 2 slots)", - "gasUsed": 7965 + "gasUsed": 7739 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetThirdFieldLength", "name": "get field length (warm, 2 slots)", - "gasUsed": 1962 + "gasUsed": 1734 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 22898 + "gasUsed": 22091 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 16928 + "gasUsed": 16098 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 24647 + "gasUsed": 23840 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 16678 + "gasUsed": 15846 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access non-existing record", - "gasUsed": 6533 + "gasUsed": 6160 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access static field of non-existing record", - "gasUsed": 1481 + "gasUsed": 1336 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access dynamic field of non-existing record", - "gasUsed": 2449 + "gasUsed": 2153 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access length of dynamic field of non-existing record", - "gasUsed": 1335 + "gasUsed": 1103 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access slice of dynamic field of non-existing record", - "gasUsed": 1631 + "gasUsed": 1564 }, { "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 9470 + "gasUsed": 8791 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "Check for existence of table (existent)", - "gasUsed": 4465 + "gasUsed": 4319 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "check for existence of table (non-existent)", - "gasUsed": 6468 + "gasUsed": 6321 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 61935 + "gasUsed": 61185 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 73748 + "gasUsed": 72938 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 25441 + "gasUsed": 24631 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 21483 + "gasUsed": 20673 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 61935 + "gasUsed": 61185 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 167808 + "gasUsed": 166460 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 28269 + "gasUsed": 27194 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 22901 + "gasUsed": 21628 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 14558 + "gasUsed": 13647 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 37206 + "gasUsed": 36275 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 620356 + "gasUsed": 619512 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get field layout (warm)", - "gasUsed": 4479 + "gasUsed": 4333 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get value schema (warm)", - "gasUsed": 5033 + "gasUsed": 4885 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get key schema (warm)", - "gasUsed": 9281 + "gasUsed": 8983 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 104856 + "gasUsed": 104055 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "get complex record with dynamic data (4 slots)", - "gasUsed": 5105 + "gasUsed": 4591 }, { "file": "test/StoreCoreGas.t.sol", @@ -741,109 +741,109 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "compare: Set complex record with dynamic data using abi.encode", - "gasUsed": 267372 + "gasUsed": 267368 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "set dynamic length of dynamic index 0", - "gasUsed": 23082 + "gasUsed": 22852 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "set dynamic length of dynamic index 1", - "gasUsed": 1183 + "gasUsed": 952 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "reduce dynamic length of dynamic index 0", - "gasUsed": 1174 + "gasUsed": 943 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 33831 + "gasUsed": 33391 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (1 slot)", - "gasUsed": 1482 + "gasUsed": 1337 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 32479 + "gasUsed": 32032 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (overlap 2 slot)", - "gasUsed": 2010 + "gasUsed": 1863 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 55195 + "gasUsed": 54584 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, first dynamic field)", - "gasUsed": 2627 + "gasUsed": 2319 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 33313 + "gasUsed": 32689 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, second dynamic field)", - "gasUsed": 2635 + "gasUsed": 2321 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 34181 + "gasUsed": 33740 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "get static record (1 slot)", - "gasUsed": 1734 + "gasUsed": 1588 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 56684 + "gasUsed": 56244 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "get static record (2 slots)", - "gasUsed": 1922 + "gasUsed": 1776 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 14835 + "gasUsed": 14158 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 15865 + "gasUsed": 15173 }, { "file": "test/StoreHook.t.sol", @@ -891,121 +891,121 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 59331 + "gasUsed": 58741 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: get field (warm)", - "gasUsed": 5160 + "gasUsed": 4860 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 39001 + "gasUsed": 38092 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 61323 + "gasUsed": 60746 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 61323 + "gasUsed": 60746 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: get field (warm)", - "gasUsed": 5136 + "gasUsed": 4844 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 19075 + "gasUsed": 18187 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 15453 + "gasUsed": 14612 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 17134 + "gasUsed": 16202 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 37483 + "gasUsed": 36767 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: delete record (warm)", - "gasUsed": 10992 + "gasUsed": 10265 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 33544 + "gasUsed": 32882 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testThreeSlots", "name": "StoreHooks: set field with three elements (cold)", - "gasUsed": 84011 + "gasUsed": 83434 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTwoSlots", "name": "StoreHooks: set field with two elements (cold)", - "gasUsed": 83923 + "gasUsed": 83346 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testDelete", "name": "StoreHooks: delete record (cold)", - "gasUsed": 19792 + "gasUsed": 19135 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testGet", "name": "StoreHooks: get field (cold)", - "gasUsed": 11129 + "gasUsed": 10842 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testGetItem", "name": "StoreHooks: get 1 element (cold)", - "gasUsed": 7644 + "gasUsed": 7583 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testLength", "name": "StoreHooks: get length (cold)", - "gasUsed": 7127 + "gasUsed": 6901 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 25580 + "gasUsed": 24776 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 27157 + "gasUsed": 26517 }, { "file": "test/tightcoder/DecodeSlice.t.sol", @@ -1059,18 +1059,18 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 421491 + "gasUsed": 420547 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 36809 + "gasUsed": 36369 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "get Vector2 record", - "gasUsed": 4472 + "gasUsed": 4324 } ] diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index c2b81a57a8..e57bdd0ec2 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -785,7 +785,7 @@ library StoreCoreInternal { * Compute the storage location based on tableId id and index tuple */ function _getStaticDataLocation(bytes32 tableId, bytes32[] memory keyTuple) internal pure returns (uint256) { - return uint256(keccak256(abi.encode(SLOT, tableId, keyTuple))); + return uint256(SLOT ^ tableId ^ keccak256(abi.encodePacked(keyTuple))); } /** @@ -811,14 +811,16 @@ library StoreCoreInternal { bytes32[] memory keyTuple, uint8 schemaIndex ) internal pure returns (uint256) { - return uint256(keccak256(abi.encode(SLOT, tableId, keyTuple, schemaIndex))); + // offset by 1 to avoid collision with static data + // assumes schemaIndex < 255 + return uint256(SLOT ^ tableId ^ bytes1(schemaIndex + 1) ^ keccak256(abi.encodePacked(keyTuple))); } /** * Compute the storage location for the length of the dynamic data */ function _getDynamicDataLengthLocation(bytes32 tableId, bytes32[] memory keyTuple) internal pure returns (uint256) { - return uint256(keccak256(abi.encode(SLOT, tableId, keyTuple, "length"))); + return uint256(SLOT ^ tableId ^ bytes32("length") ^ keccak256(abi.encodePacked(keyTuple))); } /** diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 30962ed0d7..73962a09ad 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -3,31 +3,31 @@ "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (cold)", - "gasUsed": 13860 + "gasUsed": 13575 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm, namespace only)", - "gasUsed": 4007 + "gasUsed": 3862 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm)", - "gasUsed": 7892 + "gasUsed": 7598 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (cold)", - "gasUsed": 13903 + "gasUsed": 13617 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (warm)", - "gasUsed": 7909 + "gasUsed": 7621 }, { "file": "test/AccessControl.t.sol", @@ -39,73 +39,73 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1519335 + "gasUsed": 1509977 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1519335 + "gasUsed": 1509977 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 183388 + "gasUsed": 180588 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1519335 + "gasUsed": 1509977 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1519335 + "gasUsed": 1509977 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 28498 + "gasUsed": 27795 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 251457 + "gasUsed": 242846 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1519335 + "gasUsed": 1509977 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 27221 + "gasUsed": 26518 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 132823 + "gasUsed": 128374 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 728346 + "gasUsed": 721204 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "Get list of keys with a given value", - "gasUsed": 7508 + "gasUsed": 7221 }, { "file": "test/KeysWithValueModule.t.sol", @@ -117,264 +117,264 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 728346 + "gasUsed": 721204 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 157348 + "gasUsed": 154259 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 728346 + "gasUsed": 721204 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 126291 + "gasUsed": 123282 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 49099 + "gasUsed": 47159 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 728346 + "gasUsed": 721204 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 163792 + "gasUsed": 160547 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 128551 + "gasUsed": 125306 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueNotQuery", "name": "CombinedHasHasValueNotQuery", - "gasUsed": 141196 + "gasUsed": 138256 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueQuery", "name": "CombinedHasHasValueQuery", - "gasUsed": 69053 + "gasUsed": 67499 }, { "file": "test/query.t.sol", "test": "testCombinedHasNotQuery", "name": "CombinedHasNotQuery", - "gasUsed": 184150 + "gasUsed": 180624 }, { "file": "test/query.t.sol", "test": "testCombinedHasQuery", "name": "CombinedHasQuery", - "gasUsed": 121994 + "gasUsed": 119405 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueNotQuery", "name": "CombinedHasValueNotQuery", - "gasUsed": 117772 + "gasUsed": 115406 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueQuery", "name": "CombinedHasValueQuery", - "gasUsed": 19164 + "gasUsed": 18590 }, { "file": "test/query.t.sol", "test": "testHasQuery", "name": "HasQuery", - "gasUsed": 27950 + "gasUsed": 27318 }, { "file": "test/query.t.sol", "test": "testHasQuery1000Keys", "name": "HasQuery with 1000 keys", - "gasUsed": 7068010 + "gasUsed": 7006500 }, { "file": "test/query.t.sol", "test": "testHasQuery100Keys", "name": "HasQuery with 100 keys", - "gasUsed": 672230 + "gasUsed": 665620 }, { "file": "test/query.t.sol", "test": "testHasValueQuery", "name": "HasValueQuery", - "gasUsed": 9259 + "gasUsed": 8972 }, { "file": "test/query.t.sol", "test": "testNotValueQuery", "name": "NotValueQuery", - "gasUsed": 62652 + "gasUsed": 61098 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "register a callbound delegation", - "gasUsed": 133325 + "gasUsed": 131597 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "call a system via a callbound delegation", - "gasUsed": 49383 + "gasUsed": 48088 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "register a timebound delegation", - "gasUsed": 127681 + "gasUsed": 125956 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "call a system via a timebound delegation", - "gasUsed": 38474 + "gasUsed": 37611 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 787645 + "gasUsed": 778452 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 67456 + "gasUsed": 66166 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 771167 + "gasUsed": 762405 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 67456 + "gasUsed": 66166 }, { "file": "test/World.t.sol", "test": "testCall", "name": "call a system via the World", - "gasUsed": 19564 + "gasUsed": 18989 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "register an unlimited delegation", - "gasUsed": 59044 + "gasUsed": 58038 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "call a system via an unlimited delegation", - "gasUsed": 19950 + "gasUsed": 19375 }, { "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 13886 + "gasUsed": 13312 }, { "file": "test/World.t.sol", "test": "testPushToField", "name": "Push data to the table", - "gasUsed": 93261 + "gasUsed": 92251 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 75414 + "gasUsed": 74121 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 68663 + "gasUsed": 67370 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 96008 + "gasUsed": 94714 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 146378 + "gasUsed": 144356 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 90581 + "gasUsed": 89288 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 685344 + "gasUsed": 681525 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 41899 + "gasUsed": 41325 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 41344 + "gasUsed": 40770 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 32940 + "gasUsed": 31993 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 19729 + "gasUsed": 18783 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 35373 + "gasUsed": 34590 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 22578 + "gasUsed": 21795 } ] From 8c359581483cb083e0ff615c6e06e114f5a3be3b Mon Sep 17 00:00:00 2001 From: Boffee Date: Fri, 15 Sep 2023 18:30:28 -0500 Subject: [PATCH 2/4] feat(store): add slots for dynamic data and its length --- packages/store/src/StoreCore.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index e57bdd0ec2..751379145c 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -586,6 +586,8 @@ library StoreCore { library StoreCoreInternal { bytes32 internal constant SLOT = keccak256("mud.store"); + bytes32 internal constant DYNMAIC_DATA_SLOT = keccak256("mud.store.dynamicData"); + bytes32 internal constant DYNAMIC_DATA_LENGTH_SLOT = keccak256("mud.store.dynamicDataLength"); /************************************************************************ * @@ -811,16 +813,14 @@ library StoreCoreInternal { bytes32[] memory keyTuple, uint8 schemaIndex ) internal pure returns (uint256) { - // offset by 1 to avoid collision with static data - // assumes schemaIndex < 255 - return uint256(SLOT ^ tableId ^ bytes1(schemaIndex + 1) ^ keccak256(abi.encodePacked(keyTuple))); + return uint256(DYNMAIC_DATA_SLOT ^ tableId ^ bytes1(schemaIndex) ^ keccak256(abi.encodePacked(keyTuple))); } /** * Compute the storage location for the length of the dynamic data */ function _getDynamicDataLengthLocation(bytes32 tableId, bytes32[] memory keyTuple) internal pure returns (uint256) { - return uint256(SLOT ^ tableId ^ bytes32("length") ^ keccak256(abi.encodePacked(keyTuple))); + return uint256(DYNAMIC_DATA_LENGTH_SLOT ^ tableId ^ keccak256(abi.encodePacked(keyTuple))); } /** From 063e28dc064c3eafee0a810b402d783013c91f10 Mon Sep 17 00:00:00 2001 From: Boffee Date: Fri, 15 Sep 2023 18:37:50 -0500 Subject: [PATCH 3/4] fix(store): tableId need to be hashed tableId are strings that the user define, not hashes. If this is used to resolve storage location a user can access any storage location by picking the right tableId --- packages/store/gas-report.json | 160 +++++++++++++++---------------- packages/store/src/StoreCore.sol | 6 +- packages/world/gas-report.json | 122 +++++++++++------------ 3 files changed, 144 insertions(+), 144 deletions(-) diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 314f78294b..06a9b7a2d7 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -309,7 +309,7 @@ "file": "test/KeyEncoding.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register KeyEncoding table", - "gasUsed": 696963 + "gasUsed": 696776 }, { "file": "test/Mixed.t.sol", @@ -321,19 +321,19 @@ "file": "test/Mixed.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Mixed table", - "gasUsed": 559124 + "gasUsed": 558938 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "set record in Mixed", - "gasUsed": 107832 + "gasUsed": 107648 }, { "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "get record from Mixed", - "gasUsed": 9118 + "gasUsed": 8998 }, { "file": "test/PackedCounter.t.sol", @@ -519,217 +519,217 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (cold, 1 slot)", - "gasUsed": 8363 + "gasUsed": 8282 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (warm, 1 slot)", - "gasUsed": 2431 + "gasUsed": 2349 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (semi-cold, 1 slot)", - "gasUsed": 4434 + "gasUsed": 4354 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetFieldSlice", "name": "get field slice (warm, 2 slots)", - "gasUsed": 4660 + "gasUsed": 4580 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetSecondFieldLength", "name": "get field length (cold, 1 slot)", - "gasUsed": 7739 + "gasUsed": 7757 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetSecondFieldLength", "name": "get field length (warm, 1 slot)", - "gasUsed": 1735 + "gasUsed": 1752 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetThirdFieldLength", "name": "get field length (warm due to , 2 slots)", - "gasUsed": 7739 + "gasUsed": 7757 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testGetThirdFieldLength", "name": "get field length (warm, 2 slots)", - "gasUsed": 1734 + "gasUsed": 1752 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 22091 + "gasUsed": 21982 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 16098 + "gasUsed": 15990 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 23840 + "gasUsed": 23731 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 15846 + "gasUsed": 15739 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access non-existing record", - "gasUsed": 6160 + "gasUsed": 6198 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access static field of non-existing record", - "gasUsed": 1336 + "gasUsed": 1357 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access dynamic field of non-existing record", - "gasUsed": 2153 + "gasUsed": 2090 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access length of dynamic field of non-existing record", - "gasUsed": 1103 + "gasUsed": 1120 }, { "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access slice of dynamic field of non-existing record", - "gasUsed": 1564 + "gasUsed": 1484 }, { "file": "test/StoreCoreGas.t.sol", "test": "testDeleteData", "name": "delete record (complex data, 3 slots)", - "gasUsed": 8791 + "gasUsed": 8768 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "Check for existence of table (existent)", - "gasUsed": 4319 + "gasUsed": 4340 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHasFieldLayout", "name": "check for existence of table (non-existent)", - "gasUsed": 6321 + "gasUsed": 6342 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "register subscriber", - "gasUsed": 61185 + "gasUsed": 60975 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 72938 + "gasUsed": 72842 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 24631 + "gasUsed": 24535 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "delete record on table with subscriber", - "gasUsed": 20673 + "gasUsed": 20577 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "register subscriber", - "gasUsed": 61185 + "gasUsed": 60975 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 166460 + "gasUsed": 166229 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 27194 + "gasUsed": 26926 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "delete (dynamic) record on table with subscriber", - "gasUsed": 21628 + "gasUsed": 21562 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 13647 + "gasUsed": 13461 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 36275 + "gasUsed": 36091 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 619512 + "gasUsed": 619276 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get field layout (warm)", - "gasUsed": 4333 + "gasUsed": 4353 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get value schema (warm)", - "gasUsed": 4885 + "gasUsed": 4906 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: get key schema (warm)", - "gasUsed": 8983 + "gasUsed": 9026 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 104055 + "gasUsed": 103869 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "get complex record with dynamic data (4 slots)", - "gasUsed": 4591 + "gasUsed": 4470 }, { "file": "test/StoreCoreGas.t.sol", @@ -747,103 +747,103 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "set dynamic length of dynamic index 0", - "gasUsed": 22852 + "gasUsed": 22870 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "set dynamic length of dynamic index 1", - "gasUsed": 952 + "gasUsed": 970 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicDataLength", "name": "reduce dynamic length of dynamic index 0", - "gasUsed": 943 + "gasUsed": 960 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 33391 + "gasUsed": 33349 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (1 slot)", - "gasUsed": 1337 + "gasUsed": 1358 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 32032 + "gasUsed": 31991 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (overlap 2 slot)", - "gasUsed": 1863 + "gasUsed": 1884 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 54584 + "gasUsed": 54462 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, first dynamic field)", - "gasUsed": 2319 + "gasUsed": 2258 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 32689 + "gasUsed": 32569 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get dynamic field (1 slot, second dynamic field)", - "gasUsed": 2321 + "gasUsed": 2260 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 33740 + "gasUsed": 33698 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "get static record (1 slot)", - "gasUsed": 1588 + "gasUsed": 1609 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 56244 + "gasUsed": 56203 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "get static record (2 slots)", - "gasUsed": 1776 + "gasUsed": 1796 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 14158 + "gasUsed": 13955 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 15173 + "gasUsed": 14971 }, { "file": "test/StoreHook.t.sol", @@ -891,121 +891,121 @@ "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 58741 + "gasUsed": 58615 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: get field (warm)", - "gasUsed": 4860 + "gasUsed": 4798 }, { "file": "test/tables/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 38092 + "gasUsed": 37906 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 60746 + "gasUsed": 60619 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 60746 + "gasUsed": 60619 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: get field (warm)", - "gasUsed": 4844 + "gasUsed": 4781 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 18187 + "gasUsed": 17999 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 14612 + "gasUsed": 14507 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 16202 + "gasUsed": 16020 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 36767 + "gasUsed": 36570 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: delete record (warm)", - "gasUsed": 10265 + "gasUsed": 10248 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 32882 + "gasUsed": 32766 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testThreeSlots", "name": "StoreHooks: set field with three elements (cold)", - "gasUsed": 83434 + "gasUsed": 83307 }, { "file": "test/tables/StoreHooks.t.sol", "test": "testTwoSlots", "name": "StoreHooks: set field with two elements (cold)", - "gasUsed": 83346 + "gasUsed": 83218 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testDelete", "name": "StoreHooks: delete record (cold)", - "gasUsed": 19135 + "gasUsed": 19108 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testGet", "name": "StoreHooks: get field (cold)", - "gasUsed": 10842 + "gasUsed": 10778 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testGetItem", "name": "StoreHooks: get 1 element (cold)", - "gasUsed": 7583 + "gasUsed": 7502 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testLength", "name": "StoreHooks: get length (cold)", - "gasUsed": 6901 + "gasUsed": 6918 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 24776 + "gasUsed": 24666 }, { "file": "test/tables/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 26517 + "gasUsed": 26309 }, { "file": "test/tightcoder/DecodeSlice.t.sol", @@ -1059,18 +1059,18 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 420547 + "gasUsed": 420367 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 36369 + "gasUsed": 36327 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "get Vector2 record", - "gasUsed": 4324 + "gasUsed": 4345 } ] diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index 751379145c..d47c3ccdf2 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -787,7 +787,7 @@ library StoreCoreInternal { * Compute the storage location based on tableId id and index tuple */ function _getStaticDataLocation(bytes32 tableId, bytes32[] memory keyTuple) internal pure returns (uint256) { - return uint256(SLOT ^ tableId ^ keccak256(abi.encodePacked(keyTuple))); + return uint256(SLOT ^ keccak256(abi.encodePacked(tableId, keyTuple))); } /** @@ -813,14 +813,14 @@ library StoreCoreInternal { bytes32[] memory keyTuple, uint8 schemaIndex ) internal pure returns (uint256) { - return uint256(DYNMAIC_DATA_SLOT ^ tableId ^ bytes1(schemaIndex) ^ keccak256(abi.encodePacked(keyTuple))); + return uint256(DYNMAIC_DATA_SLOT ^ bytes1(schemaIndex) ^ keccak256(abi.encodePacked(tableId, keyTuple))); } /** * Compute the storage location for the length of the dynamic data */ function _getDynamicDataLengthLocation(bytes32 tableId, bytes32[] memory keyTuple) internal pure returns (uint256) { - return uint256(DYNAMIC_DATA_LENGTH_SLOT ^ tableId ^ keccak256(abi.encodePacked(keyTuple))); + return uint256(DYNAMIC_DATA_LENGTH_SLOT ^ keccak256(abi.encodePacked(tableId, keyTuple))); } /** diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 73962a09ad..c9312d3dfa 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -3,31 +3,31 @@ "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (cold)", - "gasUsed": 13575 + "gasUsed": 13615 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm, namespace only)", - "gasUsed": 3862 + "gasUsed": 3883 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm)", - "gasUsed": 7598 + "gasUsed": 7640 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (cold)", - "gasUsed": 13617 + "gasUsed": 13658 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (warm)", - "gasUsed": 7621 + "gasUsed": 7663 }, { "file": "test/AccessControl.t.sol", @@ -39,73 +39,73 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1509977 + "gasUsed": 1509344 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1509977 + "gasUsed": 1509344 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 180588 + "gasUsed": 180445 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1509977 + "gasUsed": 1509344 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1509977 + "gasUsed": 1509344 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 27795 + "gasUsed": 27788 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 242846 + "gasUsed": 241896 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1509977 + "gasUsed": 1509344 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 26518 + "gasUsed": 26511 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 128374 + "gasUsed": 128061 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 721204 + "gasUsed": 720659 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "Get list of keys with a given value", - "gasUsed": 7221 + "gasUsed": 7157 }, { "file": "test/KeysWithValueModule.t.sol", @@ -117,264 +117,264 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 721204 + "gasUsed": 720659 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 154259 + "gasUsed": 154052 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 721204 + "gasUsed": 720659 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 123282 + "gasUsed": 122974 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 47159 + "gasUsed": 47103 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 721204 + "gasUsed": 720659 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 160547 + "gasUsed": 160364 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 125306 + "gasUsed": 125123 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueNotQuery", "name": "CombinedHasHasValueNotQuery", - "gasUsed": 138256 + "gasUsed": 137506 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueQuery", "name": "CombinedHasHasValueQuery", - "gasUsed": 67499 + "gasUsed": 67121 }, { "file": "test/query.t.sol", "test": "testCombinedHasNotQuery", "name": "CombinedHasNotQuery", - "gasUsed": 180624 + "gasUsed": 179613 }, { "file": "test/query.t.sol", "test": "testCombinedHasQuery", "name": "CombinedHasQuery", - "gasUsed": 119405 + "gasUsed": 118904 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueNotQuery", "name": "CombinedHasValueNotQuery", - "gasUsed": 115406 + "gasUsed": 114784 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueQuery", "name": "CombinedHasValueQuery", - "gasUsed": 18590 + "gasUsed": 18462 }, { "file": "test/query.t.sol", "test": "testHasQuery", "name": "HasQuery", - "gasUsed": 27318 + "gasUsed": 27213 }, { "file": "test/query.t.sol", "test": "testHasQuery1000Keys", "name": "HasQuery with 1000 keys", - "gasUsed": 7006500 + "gasUsed": 6925557 }, { "file": "test/query.t.sol", "test": "testHasQuery100Keys", "name": "HasQuery with 100 keys", - "gasUsed": 665620 + "gasUsed": 657577 }, { "file": "test/query.t.sol", "test": "testHasValueQuery", "name": "HasValueQuery", - "gasUsed": 8972 + "gasUsed": 8908 }, { "file": "test/query.t.sol", "test": "testNotValueQuery", "name": "NotValueQuery", - "gasUsed": 61098 + "gasUsed": 60720 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "register a callbound delegation", - "gasUsed": 131597 + "gasUsed": 131528 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "call a system via a callbound delegation", - "gasUsed": 48088 + "gasUsed": 48063 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "register a timebound delegation", - "gasUsed": 125956 + "gasUsed": 125886 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "call a system via a timebound delegation", - "gasUsed": 37611 + "gasUsed": 37629 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 778452 + "gasUsed": 777993 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 66166 + "gasUsed": 66139 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 762405 + "gasUsed": 761989 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 66166 + "gasUsed": 66139 }, { "file": "test/World.t.sol", "test": "testCall", "name": "call a system via the World", - "gasUsed": 18989 + "gasUsed": 18966 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "register an unlimited delegation", - "gasUsed": 58038 + "gasUsed": 57972 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "call a system via an unlimited delegation", - "gasUsed": 19375 + "gasUsed": 19352 }, { "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 13312 + "gasUsed": 13289 }, { "file": "test/World.t.sol", "test": "testPushToField", "name": "Push data to the table", - "gasUsed": 92251 + "gasUsed": 92081 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 74121 + "gasUsed": 74095 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 67370 + "gasUsed": 67344 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 94714 + "gasUsed": 94688 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 144356 + "gasUsed": 144224 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 89288 + "gasUsed": 89262 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 681525 + "gasUsed": 681227 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 41325 + "gasUsed": 41302 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 40770 + "gasUsed": 40747 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 31993 + "gasUsed": 31903 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 18783 + "gasUsed": 18693 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 34590 + "gasUsed": 34402 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 21795 + "gasUsed": 21607 } ] From 22caf561c4abf54f2f725e30a037e9ebf1a4e21a Mon Sep 17 00:00:00 2001 From: alvarius Date: Sat, 16 Sep 2023 18:31:00 +0100 Subject: [PATCH 4/4] Create short-dragons-shout.md --- .changeset/short-dragons-shout.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/short-dragons-shout.md diff --git a/.changeset/short-dragons-shout.md b/.changeset/short-dragons-shout.md new file mode 100644 index 0000000000..d2c8abe6f1 --- /dev/null +++ b/.changeset/short-dragons-shout.md @@ -0,0 +1,6 @@ +--- +"@latticexyz/store": patch +"@latticexyz/world": patch +--- + +Optimized the `StoreCore` hash function determining the data location to use less gas.