diff --git a/.changeset/beige-ads-melt.md b/.changeset/beige-ads-melt.md new file mode 100644 index 0000000000..01846b4024 --- /dev/null +++ b/.changeset/beige-ads-melt.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/store": patch +--- + +Storage events are now emitted after "before" hooks, so that the resulting logs are now correctly ordered and reflect onchain logic. This resolves issues with store writes and event emissions happening in "before" hooks. diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index e6d78e4c3a..1d4043de4c 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -63,7 +63,7 @@ "file": "test/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: set field", - "gasUsed": 56256 + "gasUsed": 56271 }, { "file": "test/Callbacks.t.sol", @@ -75,7 +75,7 @@ "file": "test/Callbacks.t.sol", "test": "testSetAndGet", "name": "Callbacks: push 1 element", - "gasUsed": 32514 + "gasUsed": 32530 }, { "file": "test/FieldLayout.t.sol", @@ -369,7 +369,7 @@ "file": "test/KeyEncoding.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register KeyEncoding table", - "gasUsed": 719032 + "gasUsed": 719062 }, { "file": "test/Mixed.t.sol", @@ -393,7 +393,7 @@ "file": "test/Mixed.t.sol", "test": "testSetGetDeleteExternal", "name": "set record in Mixed (external, cold)", - "gasUsed": 108527 + "gasUsed": 108528 }, { "file": "test/Mixed.t.sol", @@ -411,7 +411,7 @@ "file": "test/Mixed.t.sol", "test": "testSetGetDeleteInternal", "name": "set record in Mixed (internal, cold)", - "gasUsed": 103281 + "gasUsed": 103282 }, { "file": "test/Mixed.t.sol", @@ -669,25 +669,25 @@ "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (cold, 1 slot, 1 uint32 item)", - "gasUsed": 18032 + "gasUsed": 18041 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromSecondField", "name": "pop from field (warm, 1 slot, 1 uint32 item)", - "gasUsed": 12039 + "gasUsed": 12049 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (cold, 2 slots, 10 uint32 items)", - "gasUsed": 15800 + "gasUsed": 15810 }, { "file": "test/StoreCoreDynamic.t.sol", "test": "testPopFromThirdField", "name": "pop from field (warm, 2 slots, 10 uint32 items)", - "gasUsed": 11807 + "gasUsed": 11818 }, { "file": "test/StoreCoreGas.t.sol", @@ -759,13 +759,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set record on table with subscriber", - "gasUsed": 72361 + "gasUsed": 72385 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 19813 + "gasUsed": 19837 }, { "file": "test/StoreCoreGas.t.sol", @@ -783,13 +783,13 @@ "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) record on table with subscriber", - "gasUsed": 165516 + "gasUsed": 165525 }, { "file": "test/StoreCoreGas.t.sol", "test": "testHooksDynamicData", "name": "set (dynamic) field on table with subscriber", - "gasUsed": 24424 + "gasUsed": 24446 }, { "file": "test/StoreCoreGas.t.sol", @@ -801,19 +801,19 @@ "file": "test/StoreCoreGas.t.sol", "test": "testPushToDynamicField", "name": "push to field (1 slot, 1 uint32 item)", - "gasUsed": 9459 + "gasUsed": 9475 }, { "file": "test/StoreCoreGas.t.sol", "test": "testPushToDynamicField", "name": "push to field (2 slots, 10 uint32 items)", - "gasUsed": 32129 + "gasUsed": 32150 }, { "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "StoreCore: register table", - "gasUsed": 640914 + "gasUsed": 640944 }, { "file": "test/StoreCoreGas.t.sol", @@ -837,7 +837,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetDynamicData", "name": "set complex record with dynamic data (4 slots)", - "gasUsed": 102512 + "gasUsed": 102513 }, { "file": "test/StoreCoreGas.t.sol", @@ -879,7 +879,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 31224 + "gasUsed": 31252 }, { "file": "test/StoreCoreGas.t.sol", @@ -891,7 +891,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 29877 + "gasUsed": 29908 }, { "file": "test/StoreCoreGas.t.sol", @@ -903,7 +903,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, first dynamic field)", - "gasUsed": 53945 + "gasUsed": 53961 }, { "file": "test/StoreCoreGas.t.sol", @@ -915,7 +915,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set dynamic field (1 slot, second dynamic field)", - "gasUsed": 32168 + "gasUsed": 32186 }, { "file": "test/StoreCoreGas.t.sol", @@ -927,7 +927,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticData", "name": "set static record (1 slot)", - "gasUsed": 32756 + "gasUsed": 32782 }, { "file": "test/StoreCoreGas.t.sol", @@ -939,7 +939,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetStaticDataSpanningWords", "name": "set static record (2 slots)", - "gasUsed": 55260 + "gasUsed": 55289 }, { "file": "test/StoreCoreGas.t.sol", @@ -951,19 +951,19 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetDataOffchainTable", "name": "StoreCore: set record in offchain table", - "gasUsed": 8082 + "gasUsed": 8093 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInDynamicField", "name": "update in field (1 slot, 1 uint32 item)", - "gasUsed": 8807 + "gasUsed": 8835 }, { "file": "test/StoreCoreGas.t.sol", "test": "testUpdateInDynamicField", "name": "push to field (2 slots, 6 uint64 items)", - "gasUsed": 9253 + "gasUsed": 9282 }, { "file": "test/StoreHook.t.sol", @@ -993,13 +993,13 @@ "file": "test/StoreHooks.t.sol", "test": "testOneSlot", "name": "StoreHooks: set field with one elements (cold)", - "gasUsed": 58262 + "gasUsed": 58275 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (cold)", - "gasUsed": 58262 + "gasUsed": 58275 }, { "file": "test/StoreHooks.t.sol", @@ -1011,25 +1011,25 @@ "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (cold)", - "gasUsed": 12612 + "gasUsed": 12626 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: pop 1 element (warm)", - "gasUsed": 9946 + "gasUsed": 9958 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: push 1 element (warm)", - "gasUsed": 10629 + "gasUsed": 10646 }, { "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: update 1 element (warm)", - "gasUsed": 29855 + "gasUsed": 29886 }, { "file": "test/StoreHooks.t.sol", @@ -1041,19 +1041,19 @@ "file": "test/StoreHooks.t.sol", "test": "testTable", "name": "StoreHooks: set field (warm)", - "gasUsed": 30407 + "gasUsed": 30427 }, { "file": "test/StoreHooks.t.sol", "test": "testThreeSlots", "name": "StoreHooks: set field with three elements (cold)", - "gasUsed": 80950 + "gasUsed": 80966 }, { "file": "test/StoreHooks.t.sol", "test": "testTwoSlots", "name": "StoreHooks: set field with two elements (cold)", - "gasUsed": 80862 + "gasUsed": 80878 }, { "file": "test/StoreHooksColdLoad.t.sol", @@ -1083,13 +1083,13 @@ "file": "test/StoreHooksColdLoad.t.sol", "test": "testPop", "name": "StoreHooks: pop 1 element (cold)", - "gasUsed": 18381 + "gasUsed": 18390 }, { "file": "test/StoreHooksColdLoad.t.sol", "test": "testUpdate", "name": "StoreHooks: update 1 element (cold)", - "gasUsed": 20310 + "gasUsed": 20333 }, { "file": "test/StoreSwitch.t.sol", @@ -1155,13 +1155,13 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetFieldLayout", "name": "register Vector2 field layout", - "gasUsed": 442418 + "gasUsed": 442447 }, { "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "set Vector2 record", - "gasUsed": 33658 + "gasUsed": 33684 }, { "file": "test/Vector2.t.sol", diff --git a/packages/store/src/StoreCore.sol b/packages/store/src/StoreCore.sol index 50b2028d7d..ff64ea8598 100644 --- a/packages/store/src/StoreCore.sol +++ b/packages/store/src/StoreCore.sol @@ -298,11 +298,10 @@ library StoreCore { bytes memory dynamicData, FieldLayout fieldLayout ) internal { - // Emit event to notify indexers - emit Store_SetRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData); - // Early return if the table is an offchain table - if (tableId.getType() != RESOURCE_TABLE) { + if (tableId.getType() == RESOURCE_OFFCHAIN_TABLE) { + // Emit event to notify indexers + emit Store_SetRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData); return; } @@ -322,6 +321,9 @@ library StoreCore { } } + // Emit event to notify indexers + emit Store_SetRecord(tableId, keyTuple, staticData, encodedLengths, dynamicData); + // Store the static data at the static data location uint256 staticDataLocation = StoreCoreInternal._getStaticDataLocation(tableId, keyTuple); uint256 memoryPointer = Memory.dataPointer(staticData); @@ -387,16 +389,15 @@ library StoreCore { * @param data The data to write to the static data of the record at the start byte. */ function spliceStaticData(ResourceId tableId, bytes32[] memory keyTuple, uint48 start, bytes memory data) internal { - uint256 location = StoreCoreInternal._getStaticDataLocation(tableId, keyTuple); - - // Emit event to notify offchain indexers - emit StoreCore.Store_SpliceStaticData({ tableId: tableId, keyTuple: keyTuple, start: start, data: data }); - // Early return if the table is an offchain table - if (tableId.getType() != RESOURCE_TABLE) { + if (tableId.getType() == RESOURCE_OFFCHAIN_TABLE) { + // Emit event to notify offchain indexers + emit StoreCore.Store_SpliceStaticData({ tableId: tableId, keyTuple: keyTuple, start: start, data: data }); return; } + uint256 location = StoreCoreInternal._getStaticDataLocation(tableId, keyTuple); + // Call onBeforeSpliceStaticData hooks (before actually modifying the state, so observers have access to the previous state if needed) bytes21[] memory hooks = StoreHooks._get(tableId); for (uint256 i; i < hooks.length; i++) { @@ -411,6 +412,9 @@ library StoreCore { } } + // Emit event to notify offchain indexers + emit StoreCore.Store_SpliceStaticData({ tableId: tableId, keyTuple: keyTuple, start: start, data: data }); + // Store the provided value in storage Storage.store({ storagePointer: location, offset: start, data: data }); @@ -583,11 +587,10 @@ library StoreCore { * @param fieldLayout The field layout for the record. */ function deleteRecord(ResourceId tableId, bytes32[] memory keyTuple, FieldLayout fieldLayout) internal { - // Emit event to notify indexers - emit Store_DeleteRecord(tableId, keyTuple); - // Early return if the table is an offchain table - if (tableId.getType() != RESOURCE_TABLE) { + if (tableId.getType() == RESOURCE_OFFCHAIN_TABLE) { + // Emit event to notify indexers + emit Store_DeleteRecord(tableId, keyTuple); return; } @@ -600,6 +603,9 @@ library StoreCore { } } + // Emit event to notify indexers + emit Store_DeleteRecord(tableId, keyTuple); + // Delete static data uint256 staticDataLocation = StoreCoreInternal._getStaticDataLocation(tableId, keyTuple); Storage.store({ storagePointer: staticDataLocation, offset: 0, data: new bytes(fieldLayout.staticDataLength()) }); @@ -989,6 +995,23 @@ library StoreCoreInternal { // Update the encoded length PackedCounter updatedEncodedLengths = previousEncodedLengths.setAtIndex(dynamicFieldIndex, updatedFieldLength); + // Call onBeforeSpliceDynamicData hooks (before actually modifying the state, so observers have access to the previous state if needed) + bytes21[] memory hooks = StoreHooks._get(tableId); + for (uint256 i; i < hooks.length; i++) { + Hook hook = Hook.wrap(hooks[i]); + if (hook.isEnabled(BEFORE_SPLICE_DYNAMIC_DATA)) { + IStoreHook(hook.getAddress()).onBeforeSpliceDynamicData({ + tableId: tableId, + keyTuple: keyTuple, + dynamicFieldIndex: dynamicFieldIndex, + startWithinField: startWithinField, + deleteCount: deleteCount, + encodedLengths: previousEncodedLengths, + data: data + }); + } + } + { // Compute start index for the splice uint256 start = startWithinField; @@ -1010,23 +1033,6 @@ library StoreCoreInternal { }); } - // Call onBeforeSpliceDynamicData hooks (before actually modifying the state, so observers have access to the previous state if needed) - bytes21[] memory hooks = StoreHooks._get(tableId); - for (uint256 i; i < hooks.length; i++) { - Hook hook = Hook.wrap(hooks[i]); - if (hook.isEnabled(BEFORE_SPLICE_DYNAMIC_DATA)) { - IStoreHook(hook.getAddress()).onBeforeSpliceDynamicData({ - tableId: tableId, - keyTuple: keyTuple, - dynamicFieldIndex: dynamicFieldIndex, - startWithinField: startWithinField, - deleteCount: deleteCount, - encodedLengths: previousEncodedLengths, - data: data - }); - } - } - // Store the updated encoded lengths in storage if (previousFieldLength != updatedFieldLength) { uint256 dynamicSchemaLengthSlot = _getDynamicDataLengthLocation(tableId, keyTuple); diff --git a/packages/world-modules/gas-report.json b/packages/world-modules/gas-report.json index 87d1a9b1d4..885089bac9 100644 --- a/packages/world-modules/gas-report.json +++ b/packages/world-modules/gas-report.json @@ -3,139 +3,139 @@ "file": "test/ERC20.t.sol", "test": "testApprove", "name": "approve", - "gasUsed": 114344 + "gasUsed": 114366 }, { "file": "test/ERC20.t.sol", "test": "testBurn", "name": "burn", - "gasUsed": 75896 + "gasUsed": 75931 }, { "file": "test/ERC20.t.sol", "test": "testMint", "name": "mint", - "gasUsed": 161735 + "gasUsed": 161770 }, { "file": "test/ERC20.t.sol", "test": "testTransfer", "name": "transfer", - "gasUsed": 92978 + "gasUsed": 93016 }, { "file": "test/ERC20.t.sol", "test": "testTransferFrom", "name": "transferFrom", - "gasUsed": 130295 + "gasUsed": 130355 }, { "file": "test/ERC721.t.sol", "test": "testApproveAllGas", "name": "setApprovalForAll", - "gasUsed": 113971 + "gasUsed": 113993 }, { "file": "test/ERC721.t.sol", "test": "testApproveGas", "name": "approve", - "gasUsed": 87980 + "gasUsed": 87999 }, { "file": "test/ERC721.t.sol", "test": "testBurnGas", "name": "burn", - "gasUsed": 101880 + "gasUsed": 101937 }, { "file": "test/ERC721.t.sol", "test": "testMintGas", "name": "mint", - "gasUsed": 169463 + "gasUsed": 169501 }, { "file": "test/ERC721.t.sol", "test": "testSafeMintToEOAGas", "name": "safeMint", - "gasUsed": 169734 + "gasUsed": 169772 }, { "file": "test/ERC721.t.sol", "test": "testSafeTransferFromToEOAGas", "name": "safeTransferFrom", - "gasUsed": 143698 + "gasUsed": 143774 }, { "file": "test/ERC721.t.sol", "test": "testTransferFromGas", "name": "transferFrom", - "gasUsed": 136858 + "gasUsed": 136934 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1413282 + "gasUsed": 1413433 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1413282 + "gasUsed": 1413433 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 158829 + "gasUsed": 158854 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1413282 + "gasUsed": 1413433 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1413282 + "gasUsed": 1413433 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 22497 + "gasUsed": 22492 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 155864 + "gasUsed": 155971 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1413282 + "gasUsed": 1413433 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 21219 + "gasUsed": 21214 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 85046 + "gasUsed": 85089 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 668083 + "gasUsed": 668206 }, { "file": "test/KeysWithValueModule.t.sol", @@ -153,49 +153,49 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 668083 + "gasUsed": 668206 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 135435 + "gasUsed": 135437 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 668083 + "gasUsed": 668206 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 103819 + "gasUsed": 103840 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 36501 + "gasUsed": 36489 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 668083 + "gasUsed": 668206 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 146671 + "gasUsed": 146672 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 111430 + "gasUsed": 111431 }, { "file": "test/query.t.sol", @@ -267,60 +267,60 @@ "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "register a callbound delegation", - "gasUsed": 118319 + "gasUsed": 118347 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "call a system via a callbound delegation", - "gasUsed": 36703 + "gasUsed": 36697 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromSystemDelegation", "name": "register a systembound delegation", - "gasUsed": 115875 + "gasUsed": 115900 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromSystemDelegation", "name": "call a system via a systembound delegation", - "gasUsed": 33846 + "gasUsed": 33869 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "register a timebound delegation", - "gasUsed": 112813 + "gasUsed": 112823 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "call a system via a timebound delegation", - "gasUsed": 26815 + "gasUsed": 26809 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 694780 + "gasUsed": 694917 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 51041 + "gasUsed": 51045 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 663774 + "gasUsed": 663866 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 51041 + "gasUsed": 51045 } ] diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 9caba2f8e9..5c87427efd 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -69,7 +69,7 @@ "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "register an unlimited delegation", - "gasUsed": 47632 + "gasUsed": 47651 }, { "file": "test/World.t.sol", @@ -81,79 +81,79 @@ "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 9852 + "gasUsed": 9846 }, { "file": "test/World.t.sol", "test": "testPushToDynamicField", "name": "Push data to the table", - "gasUsed": 85826 + "gasUsed": 85842 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 83138 + "gasUsed": 83156 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 120932 + "gasUsed": 120962 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 80444 + "gasUsed": 80462 }, { "file": "test/World.t.sol", "test": "testRegisterSystem", "name": "register a system", - "gasUsed": 164317 + "gasUsed": 164349 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 528393 + "gasUsed": 528422 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 36896 + "gasUsed": 36912 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 39039 + "gasUsed": 39056 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromDynamicField", "name": "pop 1 address (cold)", - "gasUsed": 25617 + "gasUsed": 25627 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromDynamicField", "name": "pop 1 address (warm)", - "gasUsed": 12763 + "gasUsed": 12773 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testSpliceDynamicData", "name": "update in field 1 item (cold)", - "gasUsed": 25968 + "gasUsed": 25990 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testSpliceDynamicData", "name": "update in field 1 item (warm)", - "gasUsed": 13169 + "gasUsed": 13191 }, { "file": "test/WorldResourceId.t.sol",