diff --git a/.changeset/tough-flowers-breathe.md b/.changeset/tough-flowers-breathe.md new file mode 100644 index 0000000000..73480b8afd --- /dev/null +++ b/.changeset/tough-flowers-breathe.md @@ -0,0 +1,6 @@ +--- +"@latticexyz/store": patch +"@latticexyz/world": patch +--- + +Simplified a couple internal constants used for bitshifting. diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 866d3ea5a4..808cfb2080 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -411,7 +411,7 @@ "file": "test/ResourceId.t.sol", "test": "testEncode", "name": "encode table ID with name and type", - "gasUsed": 185 + "gasUsed": 80 }, { "file": "test/ResourceId.t.sol", diff --git a/packages/store/src/ResourceId.sol b/packages/store/src/ResourceId.sol index 39be771465..9c7a8d3398 100644 --- a/packages/store/src/ResourceId.sol +++ b/packages/store/src/ResourceId.sol @@ -3,15 +3,14 @@ pragma solidity >=0.8.21; type ResourceId is bytes32; -uint256 constant TYPE_BYTES = 2; -uint256 constant NAME_BYTES = 32 - TYPE_BYTES; -uint256 constant BYTES_TO_BITS = 8; +uint256 constant TYPE_BITS = 2 * 8; +uint256 constant NAME_BITS = 32 * 8 - TYPE_BITS; bytes32 constant TYPE_MASK = bytes32(hex"ffff"); library ResourceIdLib { function encode(bytes2 typeId, bytes30 name) internal pure returns (ResourceId) { - return ResourceId.wrap(bytes32(typeId) | (bytes32(name) >> (TYPE_BYTES * BYTES_TO_BITS))); + return ResourceId.wrap(bytes32(typeId) | (bytes32(name) >> TYPE_BITS)); } } diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 62aff370c5..5e79e0c3f6 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -3,175 +3,175 @@ "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (cold)", - "gasUsed": 7134 + "gasUsed": 6984 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm, namespace only)", - "gasUsed": 1682 + "gasUsed": 1532 }, { "file": "test/AccessControl.t.sol", "test": "testAccessControl", "name": "AccessControl: hasAccess (warm)", - "gasUsed": 3142 + "gasUsed": 2992 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (cold)", - "gasUsed": 7177 + "gasUsed": 7027 }, { "file": "test/AccessControl.t.sol", "test": "testRequireAccess", "name": "AccessControl: requireAccess (warm)", - "gasUsed": 3180 + "gasUsed": 3030 }, { "file": "test/CallBatch.t.sol", "test": "testCallBatchReturnData", "name": "call systems with callBatch", - "gasUsed": 45624 + "gasUsed": 45264 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1415285 + "gasUsed": 1413281 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1415285 + "gasUsed": 1413281 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 158224 + "gasUsed": 157774 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1415285 + "gasUsed": 1413281 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1415285 + "gasUsed": 1413281 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 22242 + "gasUsed": 22092 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 160593 + "gasUsed": 159243 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1415285 + "gasUsed": 1413281 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 20964 + "gasUsed": 20814 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 85709 + "gasUsed": 84959 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 656381 + "gasUsed": 654836 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "Get list of keys with a given value", - "gasUsed": 6186 + "gasUsed": 5709 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetTargetTableId", "name": "compute the target table selector", - "gasUsed": 3101 + "gasUsed": 2624 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 656381 + "gasUsed": 654836 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 135635 + "gasUsed": 134702 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 656381 + "gasUsed": 654836 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 105976 + "gasUsed": 105043 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 35409 + "gasUsed": 34626 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 656381 + "gasUsed": 654836 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 148384 + "gasUsed": 146968 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 113143 + "gasUsed": 111727 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueNotQuery", "name": "CombinedHasHasValueNotQuery", - "gasUsed": 104642 + "gasUsed": 103211 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueQuery", "name": "CombinedHasHasValueQuery", - "gasUsed": 54376 + "gasUsed": 52945 }, { "file": "test/query.t.sol", @@ -189,13 +189,13 @@ "file": "test/query.t.sol", "test": "testCombinedHasValueNotQuery", "name": "CombinedHasValueNotQuery", - "gasUsed": 83695 + "gasUsed": 83218 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueQuery", "name": "CombinedHasValueQuery", - "gasUsed": 16659 + "gasUsed": 15705 }, { "file": "test/query.t.sol", @@ -219,181 +219,181 @@ "file": "test/query.t.sol", "test": "testHasValueQuery", "name": "HasValueQuery", - "gasUsed": 7998 + "gasUsed": 7521 }, { "file": "test/query.t.sol", "test": "testNotValueQuery", "name": "NotValueQuery", - "gasUsed": 47972 + "gasUsed": 46541 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "register a callbound delegation", - "gasUsed": 114771 + "gasUsed": 114534 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromCallboundDelegation", "name": "call a system via a callbound delegation", - "gasUsed": 34014 + "gasUsed": 33774 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "register a timebound delegation", - "gasUsed": 109266 + "gasUsed": 109029 }, { "file": "test/StandardDelegationsModule.t.sol", "test": "testCallFromTimeboundDelegation", "name": "call a system via a timebound delegation", - "gasUsed": 27019 + "gasUsed": 26779 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 680060 + "gasUsed": 678565 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 52189 + "gasUsed": 51919 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 647141 + "gasUsed": 646138 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 52189 + "gasUsed": 51919 }, { "file": "test/World.t.sol", "test": "testCall", "name": "call a system via the World", - "gasUsed": 12679 + "gasUsed": 12409 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "register an unlimited delegation", - "gasUsed": 50659 + "gasUsed": 50539 }, { "file": "test/World.t.sol", "test": "testCallFromUnlimitedDelegation", "name": "call a system via an unlimited delegation", - "gasUsed": 12916 + "gasUsed": 12796 }, { "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 9174 + "gasUsed": 9024 }, { "file": "test/World.t.sol", "test": "testPushToField", "name": "Push data to the table", - "gasUsed": 86848 + "gasUsed": 86698 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 59383 + "gasUsed": 58902 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 53008 + "gasUsed": 52738 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 79949 + "gasUsed": 79468 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 123261 + "gasUsed": 123141 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 74921 + "gasUsed": 74651 }, { "file": "test/World.t.sol", "test": "testRegisterSystem", "name": "register a system", - "gasUsed": 165814 + "gasUsed": 165292 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 641197 + "gasUsed": 640825 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 37364 + "gasUsed": 37214 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 36490 + "gasUsed": 36340 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 24649 + "gasUsed": 24499 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 13795 + "gasUsed": 13645 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 25213 + "gasUsed": 25063 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 14418 + "gasUsed": 14268 }, { "file": "test/WorldResourceId.t.sol", "test": "testGetNamespace", "name": "encode namespace, name and type", - "gasUsed": 150 + "gasUsed": 33 }, { "file": "test/WorldResourceId.t.sol", "test": "testGetNamespaceId", "name": "get namespace ID from a resource ID", - "gasUsed": 174 + "gasUsed": 22 }, { "file": "test/WorldResourceId.t.sol", diff --git a/packages/world/src/WorldResourceId.sol b/packages/world/src/WorldResourceId.sol index 1a5b641c14..4d9f92e4c7 100644 --- a/packages/world/src/WorldResourceId.sol +++ b/packages/world/src/WorldResourceId.sol @@ -2,19 +2,18 @@ pragma solidity >=0.8.21; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; -import { ResourceId, ResourceIdInstance, TYPE_BYTES } from "@latticexyz/store/src/ResourceId.sol"; +import { ResourceId, ResourceIdInstance, TYPE_BITS } from "@latticexyz/store/src/ResourceId.sol"; import { ROOT_NAMESPACE, ROOT_NAME } from "./constants.sol"; import { RESOURCE_NAMESPACE, MASK_RESOURCE_NAMESPACE } from "./worldResourceTypes.sol"; -uint256 constant NAMESPACE_BYTES = 14; -uint256 constant NAME_BYTES = 16; -uint256 constant BYTES_TO_BITS = 8; +uint256 constant NAMESPACE_BITS = 14 * 8; +uint256 constant NAME_BITS = 16 * 8; bytes16 constant ROOT_NAMESPACE_STRING = bytes16("ROOT_NAMESPACE"); bytes16 constant ROOT_NAME_STRING = bytes16("ROOT_NAME"); -bytes32 constant NAMESPACE_MASK = bytes32(~bytes14("")) >> (TYPE_BYTES * BYTES_TO_BITS); +bytes32 constant NAMESPACE_MASK = bytes32(~bytes14("")) >> (TYPE_BITS); library WorldResourceIdLib { /** @@ -28,9 +27,7 @@ library WorldResourceIdLib { function encode(bytes2 typeId, bytes14 namespace, bytes16 name) internal pure returns (ResourceId) { return ResourceId.wrap( - bytes32(typeId) | - (bytes32(namespace) >> (TYPE_BYTES * BYTES_TO_BITS)) | - (bytes32(name) >> ((TYPE_BYTES + NAMESPACE_BYTES) * BYTES_TO_BITS)) + bytes32(typeId) | (bytes32(namespace) >> TYPE_BITS) | (bytes32(name) >> (TYPE_BITS + NAMESPACE_BITS)) ); } @@ -38,7 +35,7 @@ library WorldResourceIdLib { * Create a 32-byte resource ID from a namespace. */ function encodeNamespace(bytes14 namespace) internal pure returns (ResourceId) { - return ResourceId.wrap(bytes32(RESOURCE_NAMESPACE) | (bytes32(namespace) >> (TYPE_BYTES * BYTES_TO_BITS))); + return ResourceId.wrap(bytes32(RESOURCE_NAMESPACE) | (bytes32(namespace) >> (TYPE_BITS))); } /** @@ -57,7 +54,7 @@ library WorldResourceIdInstance { * Get the namespace of a resource ID. */ function getNamespace(ResourceId resourceId) internal pure returns (bytes14) { - return bytes14(ResourceId.unwrap(resourceId) << (TYPE_BYTES * BYTES_TO_BITS)); + return bytes14(ResourceId.unwrap(resourceId) << (TYPE_BITS)); } /** @@ -71,7 +68,7 @@ library WorldResourceIdInstance { * Get the name of a resource ID. */ function getName(ResourceId resourceId) internal pure returns (bytes16) { - return bytes16(ResourceId.unwrap(resourceId) << ((TYPE_BYTES + NAMESPACE_BYTES) * BYTES_TO_BITS)); + return bytes16(ResourceId.unwrap(resourceId) << (TYPE_BITS + NAMESPACE_BITS)); } /** diff --git a/packages/world/src/modules/keyswithvalue/getTargetTableId.sol b/packages/world/src/modules/keyswithvalue/getTargetTableId.sol index 4179f8cd95..1a55f06612 100644 --- a/packages/world/src/modules/keyswithvalue/getTargetTableId.sol +++ b/packages/world/src/modules/keyswithvalue/getTargetTableId.sol @@ -1,14 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.21; -import { TYPE_BYTES } from "@latticexyz/store/src/ResourceId.sol"; -import { ResourceId, WorldResourceIdInstance, NAME_BYTES } from "../../WorldResourceId.sol"; +import { TYPE_BITS } from "@latticexyz/store/src/ResourceId.sol"; +import { ResourceId, WorldResourceIdInstance, NAME_BITS } from "../../WorldResourceId.sol"; import { RESOURCE_TABLE } from "../../worldResourceTypes.sol"; -uint256 constant MODULE_NAMESPACE_BYTES = 7; -uint256 constant TABLE_NAMESPACE_BYTES = 7; -uint256 constant TABLE_NAME_BYTES = 16; -uint256 constant BYTES_TO_BITS = 8; +uint256 constant MODULE_NAMESPACE_BITS = 7 * 8; +uint256 constant TABLE_NAMESPACE_BITS = 7 * 8; +uint256 constant TABLE_NAME_BITS = 16 * 8; /** * Get a deterministic selector for the reverse mapping table for the given source table. @@ -26,8 +25,8 @@ function getTargetTableId(bytes7 moduleNamespace, ResourceId sourceTableId) pure return ResourceId.wrap( bytes32(RESOURCE_TABLE) | - (bytes32(moduleNamespace) >> (TYPE_BYTES * BYTES_TO_BITS)) | - (bytes32(sourceTableNamespace) >> ((TYPE_BYTES + MODULE_NAMESPACE_BYTES) * BYTES_TO_BITS)) | - (bytes32(tableName) >> ((TYPE_BYTES + MODULE_NAMESPACE_BYTES + TABLE_NAMESPACE_BYTES) * BYTES_TO_BITS)) + (bytes32(moduleNamespace) >> TYPE_BITS) | + (bytes32(sourceTableNamespace) >> (TYPE_BITS + MODULE_NAMESPACE_BITS)) | + (bytes32(tableName) >> (TYPE_BITS + MODULE_NAMESPACE_BITS + TABLE_NAMESPACE_BITS)) ); } diff --git a/packages/world/test/KeysWithValueModule.t.sol b/packages/world/test/KeysWithValueModule.t.sol index aac01226fb..ab05c20aaa 100644 --- a/packages/world/test/KeysWithValueModule.t.sol +++ b/packages/world/test/KeysWithValueModule.t.sol @@ -15,7 +15,7 @@ import { FieldLayoutEncodeHelper } from "@latticexyz/store/test/FieldLayoutEncod import { World } from "../src/World.sol"; import { IBaseWorld } from "../src/interfaces/IBaseWorld.sol"; -import { WorldResourceIdLib, WorldResourceIdInstance, NAME_BYTES, TYPE_BYTES } from "../src/WorldResourceId.sol"; +import { WorldResourceIdLib, WorldResourceIdInstance, NAME_BITS, TYPE_BITS } from "../src/WorldResourceId.sol"; import { ROOT_NAMESPACE } from "../src/constants.sol"; import { RESOURCE_TABLE } from "../src/worldResourceTypes.sol"; @@ -24,7 +24,7 @@ import { KeysWithValueModule } from "../src/modules/keyswithvalue/KeysWithValueM import { MODULE_NAMESPACE } from "../src/modules/keyswithvalue/constants.sol"; import { KeysWithValue } from "../src/modules/keyswithvalue/tables/KeysWithValue.sol"; import { getKeysWithValue } from "../src/modules/keyswithvalue/getKeysWithValue.sol"; -import { getTargetTableId, MODULE_NAMESPACE_BYTES, TABLE_NAMESPACE_BYTES, TYPE_BYTES } from "../src/modules/keyswithvalue/getTargetTableId.sol"; +import { getTargetTableId, MODULE_NAMESPACE_BITS, TABLE_NAMESPACE_BITS } from "../src/modules/keyswithvalue/getTargetTableId.sol"; contract KeysWithValueModuleTest is Test, GasReporter { using ResourceIdInstance for ResourceId; @@ -80,7 +80,7 @@ contract KeysWithValueModuleTest is Test, GasReporter { } function testMatchingByteSizes() public { - assertEq(MODULE_NAMESPACE_BYTES + TABLE_NAMESPACE_BYTES + NAME_BYTES + TYPE_BYTES, 32); + assertEq(MODULE_NAMESPACE_BITS + TABLE_NAMESPACE_BITS + NAME_BITS + TYPE_BITS, 256); } function testInstall() public { @@ -235,14 +235,14 @@ contract KeysWithValueModuleTest is Test, GasReporter { // The next 7 bytes are the module namespace assertEq( - bytes7(ResourceId.unwrap(_targetTableId) << (TYPE_BYTES * 8)), + bytes7(ResourceId.unwrap(_targetTableId) << (TYPE_BITS)), MODULE_NAMESPACE, "module namespace does not match" ); // followed by the first 7 bytes of the source table namespace assertEq( - bytes7(ResourceId.unwrap(_targetTableId) << ((TYPE_BYTES + MODULE_NAMESPACE_BYTES) * 8)), + bytes7(ResourceId.unwrap(_targetTableId) << (TYPE_BITS + MODULE_NAMESPACE_BITS)), bytes7(namespace), "table namespace does not match" ); diff --git a/packages/world/test/WorldResourceId.t.sol b/packages/world/test/WorldResourceId.t.sol index fe052c0c10..1ed06df233 100644 --- a/packages/world/test/WorldResourceId.t.sol +++ b/packages/world/test/WorldResourceId.t.sol @@ -5,7 +5,7 @@ import { Test, console } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { ResourceId, ResourceIdLib, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol"; -import { WorldResourceIdLib, WorldResourceIdInstance, NAMESPACE_BYTES, NAME_BYTES, TYPE_BYTES } from "../src/WorldResourceId.sol"; +import { WorldResourceIdLib, WorldResourceIdInstance, NAMESPACE_BITS, NAME_BITS, TYPE_BITS } from "../src/WorldResourceId.sol"; import { RESOURCE_SYSTEM } from "../src/worldResourceTypes.sol"; contract WorldResourceIdTest is Test, GasReporter { @@ -73,7 +73,7 @@ contract WorldResourceIdTest is Test, GasReporter { namespace: "namespace", name: "name" }); - bytes30 resourceIdWithoutType = bytes30(ResourceId.unwrap(resourceId) << (TYPE_BYTES * 8)); + bytes30 resourceIdWithoutType = bytes30(ResourceId.unwrap(resourceId) << TYPE_BITS); assertEq( ResourceId.unwrap(resourceId), ResourceId.unwrap(ResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, name: resourceIdWithoutType })) @@ -81,7 +81,7 @@ contract WorldResourceIdTest is Test, GasReporter { } function testMatchingByteSizes() public { - assertEq(NAMESPACE_BYTES + NAME_BYTES + TYPE_BYTES, 32); + assertEq(NAMESPACE_BITS + NAME_BITS + TYPE_BITS, 256); } function testFuzz(bytes14 namespace, bytes16 name, bytes2 resourceType) public {